diff --git a/.gitlab/ci/integration.yml b/.gitlab/ci/integration.yml index 7b71a7c3f7376a9a091ac85b90f2b07fd6c21c23..70ac930eac553a7495331496d45169f9b2579da3 100644 --- a/.gitlab/ci/integration.yml +++ b/.gitlab/ci/integration.yml @@ -68,6 +68,7 @@ integration:sandboxes:u-a-u: extends: .integration_template script: - ROOT_PATH=$PWD/flextesa-hard-fork dune build @src/bin_sandbox/runtest_sandbox_user_activated_upgrade_active + - ROOT_PATH=$PWD/flextesa-hard-fork dune build @src/bin_sandbox/runtest_sandbox_user_activated_upgrade_next - ROOT_PATH=$PWD/flextesa-hard-fork dune build @src/bin_sandbox/runtest_sandbox_user_activated_upgrade_alpha artifacts: paths: @@ -79,6 +80,7 @@ integration:sandboxes:daemons-upgrade: extends: .integration_template script: - ROOT_PATH=$PWD/flextesa-daemons-upgrade dune build @src/bin_sandbox/runtest_sandbox_daemons_upgrade_active + - ROOT_PATH=$PWD/flextesa-daemons-upgrade dune build @src/bin_sandbox/runtest_sandbox_daemons_upgrade_next - ROOT_PATH=$PWD/flextesa-daemons-upgrade dune build @src/bin_sandbox/runtest_sandbox_daemons_upgrade_alpha artifacts: paths: @@ -301,6 +303,120 @@ integration:008_voting_full: - poetry run pytest tests_008/test_voting_full.py -s --log-dir=tmp 2>&1 | tee tmp/008_voting_full.out | tail stage: test +integration:009_fast: + extends: .integration_python_template + script: + - poetry run pytest tests_009 -m "not slow" -s --log-dir=tmp 2>&1 | tee tmp/009_fast.out | tail + stage: test + +integration:009_baker_endorser: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_baker_endorser.py -s --log-dir=tmp 2>&1 | tee tmp/009_baker_endorser.out | tail + stage: test + +integration:009_block_times_ideal_scenario: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_block_times_ideal_scenario.py -s --log-dir=tmp 2>&1 | tee tmp/009_block_times_ideal_scenario.out | tail + stage: test + +integration:009_bootstrap: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_bootstrap.py -s --log-dir=tmp 2>&1 | tee tmp/009_bootstrap.out | tail + stage: test + +integration:009_contract: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_contract.py -s --log-dir=tmp 2>&1 | tee tmp/009_contract.out | tail + stage: test + +integration:009_contract_annotations: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_contract_annotations.py -s --log-dir=tmp 2>&1 | tee tmp/009_contract_annotations.out | tail + stage: test + +integration:009_contract_macros: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_contract_macros.py -s --log-dir=tmp 2>&1 | tee tmp/009_contract_macros.out | tail + stage: test + +integration:009_contract_onchain_opcodes: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_contract_onchain_opcodes.py -s --log-dir=tmp 2>&1 | tee tmp/009_contract_onchain_opcodes.out | tail + stage: test + +integration:009_contract_opcodes: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_contract_opcodes.py -s --log-dir=tmp 2>&1 | tee tmp/009_contract_opcodes.out | tail + stage: test + +integration:009_forge_block: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_forge_block.py -s --log-dir=tmp 2>&1 | tee tmp/009_forge_block.out | tail + stage: test + +integration:009_many_bakers: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_many_bakers.py -s --log-dir=tmp 2>&1 | tee tmp/009_many_bakers.out | tail + stage: test + +integration:009_many_nodes: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_many_nodes.py -s --log-dir=tmp 2>&1 | tee tmp/009_many_nodes.out | tail + stage: test + +integration:009_mempool: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_mempool.py -s --log-dir=tmp 2>&1 | tee tmp/009_mempool.out | tail + stage: test + +integration:009_multinode_snapshot: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_multinode_snapshot.py -s --log-dir=tmp 2>&1 | tee tmp/009_multinode_snapshot.out | tail + stage: test + +integration:009_multinode_storage_reconstruction: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_multinode_storage_reconstruction.py -s --log-dir=tmp 2>&1 | tee tmp/009_multinode_storage_reconstruction.out | tail + stage: test + +integration:009_nonce_seed_revelation: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_nonce_seed_revelation.py -s --log-dir=tmp 2>&1 | tee tmp/009_nonce_seed_revelation.out | tail + stage: test + +integration:009_perf_endorsement: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_perf_endorsement.py -s --log-dir=tmp 2>&1 | tee tmp/009_perf_endorsement.out | tail + stage: test + +integration:009_rpc: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_rpc.py -s --log-dir=tmp 2>&1 | tee tmp/009_rpc.out | tail + stage: test + +integration:009_voting_full: + extends: .integration_python_template + script: + - poetry run pytest tests_009/test_voting_full.py -s --log-dir=tmp 2>&1 | tee tmp/009_voting_full.out | tail + stage: test + integration:alpha_fast: extends: .integration_python_template script: diff --git a/.gitlab/ci/opam.yml b/.gitlab/ci/opam.yml index 76f7b0ac0a4d0bca3a90ddc1eb3c02529cd7f5cc..959784c635ff76040b8276d422b63a6f5896c845 100644 --- a/.gitlab/ci/opam.yml +++ b/.gitlab/ci/opam.yml @@ -86,6 +86,11 @@ opam:tezos-008-PtEdo2Zk-test-helpers: variables: package: tezos-008-PtEdo2Zk-test-helpers +opam:tezos-009-PsFLoren-test-helpers: + extends: .opam_template + variables: + package: tezos-009-PsFLoren-test-helpers + opam:tezos-accuser-007-PsDELPH1: extends: .opam_template variables: @@ -106,6 +111,16 @@ opam:tezos-accuser-008-PtEdo2Zk-commands: variables: package: tezos-accuser-008-PtEdo2Zk-commands +opam:tezos-accuser-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-accuser-009-PsFLoren + +opam:tezos-accuser-009-PsFLoren-commands: + extends: .opam_template + variables: + package: tezos-accuser-009-PsFLoren-commands + opam:tezos-accuser-alpha: extends: .opam_template variables: @@ -131,6 +146,11 @@ opam:tezos-baker-008-PtEdo2Zk: variables: package: tezos-baker-008-PtEdo2Zk +opam:tezos-baker-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-baker-009-PsFLoren + opam:tezos-baker-alpha: extends: .opam_template variables: @@ -156,6 +176,16 @@ opam:tezos-baking-008-PtEdo2Zk-commands: variables: package: tezos-baking-008-PtEdo2Zk-commands +opam:tezos-baking-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-baking-009-PsFLoren + +opam:tezos-baking-009-PsFLoren-commands: + extends: .opam_template + variables: + package: tezos-baking-009-PsFLoren-commands + opam:tezos-baking-alpha: extends: .opam_template variables: @@ -291,6 +321,21 @@ opam:tezos-client-008-PtEdo2Zk-commands-registration: variables: package: tezos-client-008-PtEdo2Zk-commands-registration +opam:tezos-client-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-client-009-PsFLoren + +opam:tezos-client-009-PsFLoren-commands: + extends: .opam_template + variables: + package: tezos-client-009-PsFLoren-commands + +opam:tezos-client-009-PsFLoren-commands-registration: + extends: .opam_template + variables: + package: tezos-client-009-PsFLoren-commands-registration + opam:tezos-client-alpha: extends: .opam_template variables: @@ -341,6 +386,11 @@ opam:tezos-client-sapling-008-PtEdo2Zk: variables: package: tezos-client-sapling-008-PtEdo2Zk +opam:tezos-client-sapling-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-client-sapling-009-PsFLoren + opam:tezos-client-sapling-alpha: extends: .opam_template variables: @@ -411,6 +461,11 @@ opam:tezos-embedded-protocol-008-PtEdoTez: variables: package: tezos-embedded-protocol-008-PtEdoTez +opam:tezos-embedded-protocol-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-embedded-protocol-009-PsFLoren + opam:tezos-embedded-protocol-alpha: extends: .opam_template variables: @@ -456,6 +511,16 @@ opam:tezos-endorser-008-PtEdo2Zk-commands: variables: package: tezos-endorser-008-PtEdo2Zk-commands +opam:tezos-endorser-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-endorser-009-PsFLoren + +opam:tezos-endorser-009-PsFLoren-commands: + extends: .opam_template + variables: + package: tezos-endorser-009-PsFLoren-commands + opam:tezos-endorser-alpha: extends: .opam_template variables: @@ -611,6 +676,21 @@ opam:tezos-protocol-008-PtEdoTez: variables: package: tezos-protocol-008-PtEdoTez +opam:tezos-protocol-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-protocol-009-PsFLoren + +opam:tezos-protocol-009-PsFLoren-parameters: + extends: .opam_template + variables: + package: tezos-protocol-009-PsFLoren-parameters + +opam:tezos-protocol-009-PsFLoren-tests: + extends: .opam_template + variables: + package: tezos-protocol-009-PsFLoren-tests + opam:tezos-protocol-alpha: extends: .opam_template variables: @@ -716,6 +796,11 @@ opam:tezos-protocol-functor-008-PtEdoTez: variables: package: tezos-protocol-functor-008-PtEdoTez +opam:tezos-protocol-functor-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-protocol-functor-009-PsFLoren + opam:tezos-protocol-functor-alpha: extends: .opam_template variables: @@ -771,6 +856,16 @@ opam:tezos-protocol-plugin-008-PtEdo2Zk-registerer: variables: package: tezos-protocol-plugin-008-PtEdo2Zk-registerer +opam:tezos-protocol-plugin-009-PsFLoren: + extends: .opam_template + variables: + package: tezos-protocol-plugin-009-PsFLoren + +opam:tezos-protocol-plugin-009-PsFLoren-registerer: + extends: .opam_template + variables: + package: tezos-protocol-plugin-009-PsFLoren-registerer + opam:tezos-protocol-plugin-alpha: extends: .opam_template variables: diff --git a/.gitlab/ci/unittest.yml b/.gitlab/ci/unittest.yml index 5ab60e96616df7b34a2738881e027a1c17f2fe0f..f38ae12c938ce2f7191a265af217c523bcef1d29 100644 --- a/.gitlab/ci/unittest.yml +++ b/.gitlab/ci/unittest.yml @@ -70,6 +70,8 @@ unit:alltest: - scripts/test_wrapper.sh src/proto_007_PsDELPH1/lib_protocol 007_PsDELPH1_lib_protocol - scripts/test_wrapper.sh src/proto_008_PtEdo2Zk/lib_client 008_PtEdo2Zk_lib_client - scripts/test_wrapper.sh src/proto_008_PtEdo2Zk/lib_protocol 008_PtEdo2Zk_lib_protocol + - scripts/test_wrapper.sh src/proto_009_PsFLoren/lib_client 009_PsFLoren_lib_client + - scripts/test_wrapper.sh src/proto_009_PsFLoren/lib_protocol 009_PsFLoren_lib_protocol - scripts/test_wrapper.sh src/proto_alpha/lib_client alpha_lib_client - scripts/test_wrapper.sh src/proto_alpha/lib_protocol alpha_lib_protocol - scripts/test_wrapper.sh src/tooling src_tooling diff --git a/active_protocol_versions b/active_protocol_versions index da545e34458cda05b5f8e647e2faa7fc7a016b2d..91a37650ea68d1b8513e3a8994e8011702ada386 100644 --- a/active_protocol_versions +++ b/active_protocol_versions @@ -1,3 +1,4 @@ 007-PsDELPH1 008-PtEdo2Zk +009-PsFLoren alpha diff --git a/docs/009/cli-commands.rst b/docs/009/cli-commands.rst new file mode 100644 index 0000000000000000000000000000000000000000..32dffd1b716e985f448ea755c6d3efcae3677e7b --- /dev/null +++ b/docs/009/cli-commands.rst @@ -0,0 +1,53 @@ +.. _cli_commands_009: + +********************** +Command Line Interface +********************** + +This document is a prettier output of the documentation produced by +the command line client's ``man`` command. You can obtain similar pages +using the following shell commands. + +:: + + tezos-client -protocol ProtoALphaALph man -verbosity 3 + tezos-admin-client man -verbosity 3 + +The rest of this page documents the protocol-dependent tools. +The protocol-independent tools are documented :ref:`here `. + + +.. _client_manual_009: + +Client manual +============= + +.. raw:: html + :file: tezos-client-009.html + + +.. _baker_manual_009: + +Baker manual +============ + +.. raw:: html + :file: tezos-baker-009.html + + +.. _endorser_manual_009: + +Endorser manual +=============== + +.. raw:: html + :file: tezos-endorser-009.html + + +.. _accuser_manual_009: + +Accuser manual +============== + +.. raw:: html + :file: tezos-accuser-009.html diff --git a/docs/009/glossary.rst b/docs/009/glossary.rst new file mode 100644 index 0000000000000000000000000000000000000000..d773966c9e662c012d1171ac0045690664599333 --- /dev/null +++ b/docs/009/glossary.rst @@ -0,0 +1,157 @@ +Glossary +======== + +This glossary is divided in two sections, the first one concerns Tezos, and +the second one concerns the Alpha protocol, which is the current +`economic protocol`_. + +Tezos +----- + +.. include:: ../shell/glossary.rst.h + +Protocol Alpha +-------------- + +_`Accuser` + When a node_ attempts to inject several incompatible blocks (or when it tries + to abuse the network in another similar way), another node_ can make an + accusation: show evidence of attempted abuse. The node_ making the accusation + is the accuser. + + The accuser is awarded some funds from the baking_ deposit of the accused. + + Using the tools provided by Nomadic Labs, accusation is handled by a + separate binary. + +_`Account` + An account is a unique identifier within protocol Alpha. There are different + kinds of accounts (see `Originated account`_ and `Implicit account`_). + + In the Context_, each account is associated with a balance (an amount of + tez available). + +_`Baker` + When a node_ creates a new block_, it is the baker of this block_. + Baking_ rights are distributed to different accounts based on their + available balance. Only a node_ that handles an account_ with baking_ rights + is allowed to bake; blocks created by another node_ are invalid. + The baker selects transactions from the mempool_ to be included in the block_ it bakes. + + Using the tools provided by Nomadic Labs, baking_ is handled by a + separate binary. + +_`Baking`/_`Endorsing rights` + A delegate_ is allowed to bake/endorse a block_ if he holds the + baking/endorsing right for that block_. At the start of a Cycle_, + baking and endorsing rights are computed for all the block_ heights in the + cycle_, based on the proportion of Rolls owned by each accounts. + + For each block_ height, there are several accounts that are allowed to bake. + These different accounts are given different Priorities. + + For each block_ height, there are several accounts that are allowed to + endorse. There can be multiple endorsements per block_. + +_`Contract` + See account_. + +_`Cycle` + A cycle is a set of consecutive blocks. E.g., cycle 12 started at block_ + height 49152 and ended at block_ height 53248. + + Cycles are used as a unit of “time” in the block_ chain. For example, the + different phases in the amendment voting procedures are defined based on + cycles. + +_`Delegate` + An `Implicit account`_ to which an account_ has delegated their baking_ and + `endorsing rights`_. The baking_ rights and `endorsing rights`_ are + calculated based on the total balance of tez that an account_ has been + delegated to. + +_`Delegation` + An operation_ in which an account_ balance is lent to a + delegate_. This increases the delegate_'s rolls and consequently + its Baking_ rights. The delegate_ does not control the funds from + the account_. + +_`Double baking` + When a baker_ signs two different blocks at the same height, it is called + double baking. Double baking is detrimental to the network and might be + indicative of an attempt to double spend. As such, it is punished by the + network: an accuser_ can provide proof of the double baking to be awarded + part of the baker_'s deposit. + +_`Endorser` + When a block_ is created and propagated on the network, nodes that have + `endorsing rights`_ for the matching block_ height can emit an endorsement + operation_. The accounts that emit the block_ are the endorsers of the block_. + Endorsement operations_ are included in the next block_. + + Using the tools provided by Nomadic Labs, endorsement is handled by a + separate binary. + +_`Gas` + A measure of the number of elementary operations_ performed during + the execution of a `smart contract`_. Gas is used to measure how + much computing power is used to execute a `smart contract`_. + +_`Implicit account` + An account_ that is linked to a public key. Contrary to a `smart + contract`_, an `Implicit account`_ cannot include a script and it + cannot reject incoming transactions. + + If registered, an `Implicit account`_ can act as a delegate_. + + The address of an `Implicit account`_ always starts with the + letters `tz` followed by `1`, `2` or `3` (depending on the + signature scheme) and finally the hash of the public key. + +.. _glossary_michelson_009: + +Michelson + The built-in language used by a `smart contract`_. + +_`Operations` + In protocol Alpha, the main operations are transactions (to transfer funds + or to execute smart contracts), accusations, activations, delegations, + endorsements and originations. + +_`Originated account` + See `smart contract`_. + +_`Origination` + An operation_ to create a `smart contract`_. + +_`Priority` + A rank of different baking_ rights. Each rank corresponds to a time span. A + baker_ with baking_ rights at a given priority is only allowed to bake during + the priority's corresponding time span. Baking_ outside of one's designated + priority, results in an invalid block_. + +_`Roll` + An amount of tez (e.g., 8000ꜩ) serving as a unit to determine delegates' + baking_ rights in a cycle_. A delegate_ with twice as many rolls as another + will be given twice as many rights to bake. + +_`Smart contract` + Account_ which is associated to a :ref:`Michelson ` script. They are + created with an explicit origination_ operation and are therefore + sometimes called originated accounts. The address of a smart + contract always starts with the letters ``KT1``. + +_`Transaction` + An operation_ to transfer tez between two accounts, or to run the code of a + `smart contract`_. + +_`Voting period` Any of the ``proposal``, ``exploration``, + ``cooldown``, ``promotion`` or ``adoption`` stages in the voting + procedure when ammending the `economic protocol`_. + +_`Voting listings` + The list calculated at the beginning of each `voting period`_ that contains + the staking balance (in number of rolls) of each delegate_ that owns more + than one roll_ at that moment. For each delegate_, The voting listings + reflects the weight of the vote emitted by the delegate_ when ammending the + `economic protocol`_. diff --git a/docs/009/michelson.rst b/docs/009/michelson.rst new file mode 100644 index 0000000000000000000000000000000000000000..0ef06e05a2ac457047598582dffd015d5056c462 --- /dev/null +++ b/docs/009/michelson.rst @@ -0,0 +1,3685 @@ +.. _michelson_009: + +Michelson: the language of Smart Contracts in Tezos +=================================================== + +This specification gives a detailed formal semantics of the Michelson +language, and a short explanation of how smart contracts are executed +and interact in the blockchain. + +The language is stack-based, with high level data types and primitives, +and strict static type checking. Its design cherry picks traits from +several language families. Vigilant readers will notice direct +references to Forth, Scheme, ML and Cat. + +A Michelson program is a series of instructions that are run in +sequence: each instruction receives as input the stack resulting of the +previous instruction, and rewrites it for the next one. The stack +contains both immediate values and heap allocated structures. All values +are immutable and garbage collected. + +The types of the input and output stack are fixed and monomorphic, +and the program is typechecked before being introduced into the system. +No smart contract execution can fail because an instruction has been +executed on a stack of unexpected length or contents. + +This specification gives the complete instruction set, type system and +semantics of the language. It is meant as a precise reference manual, +not an easy introduction. Even though, some examples are provided at +the end of the document and can be read first or at the same time as +the specification. The document also starts with a less formal +explanation of the context: how Michelson code interacts with the +blockchain. + +Semantics of smart contracts and transactions +--------------------------------------------- + +The Tezos ledger currently has two types of accounts that can hold +tokens (and be the destinations of transactions). + + - An implicit account is a non programmable account, whose tokens + are spendable and delegatable by a public key. Its address is + directly the public key hash, and starts with ``tz1``, ``tz2`` or + ``tz3``. + - A smart contract is a programmable account. A transaction to such + an address can provide data, and can fail for reasons decided by + its Michelson code. Its address is a unique hash that depends on + the operation that led to its creation, and starts with ``KT1``. + +From Michelson, they are indistinguishable. A safe way to think about +this is to consider that implicit accounts are smart contracts that +always succeed to receive tokens, and does nothing else. + +Intra-transaction semantics +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Alongside their tokens, smart contracts keep a piece of storage. Both +are ruled by a specific logic specified by a Michelson program. A +transaction to smart contract will provide an input value and in +option some tokens, and in return, the smart contract can modify its +storage and transfer its tokens. + +The Michelson program receives as input a stack containing a single +pair whose first element is an input value and second element the +content of the storage space. It must return a stack containing a +single pair whose first element is the list of internal operations +that it wants to emit, and second element is the new contents of the +storage space. Alternatively, a Michelson program can fail, explicitly +using a specific opcode, or because something went wrong that could +not be caught by the type system (e.g. gas exhaustion). + +A bit of polymorphism can be used at contract level, with a +lightweight system of named entrypoints: instead of an input value, +the contract can be called with an entrypoint name and an argument, +and these two component are transformed automatically in a simple and +deterministic way to an input value. This feature is available both +for users and from Michelson code. See the dedicated section. + +Inter-transaction semantics +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An operation included in the blockchain is a sequence of "external +operations" signed as a whole by a source address. These operations +are of three kinds: + + - Transactions to transfer tokens to implicit accounts or tokens and + parameters to a smart contract (or, optionally, to a specified + entrypoint of a smart contract). + - Originations to create new smart contracts from its Michelson + source code, an initial amount of tokens transferred from the + source, and an initial storage contents. + - Delegations to assign the tokens of the source to the stake of + another implicit account (without transferring any tokens). + +Smart contracts can also emit "internal operations". These are run +in sequence after the external transaction completes, as in the +following schema for a sequence of two external operations. + +:: + + +------+----------------+-------+----------------+ + | op 1 | internal ops 1 | op 2 | internal ops 2 | + +------+----------------+-------+----------------+ + +Smart contracts called by internal transactions can in turn also emit +internal operation. The interpretation of the internal operations +of a given external operation uses a stack, as in the following +example, also with two external operations. + +:: + + +-----------+---------------+--------------------------+ + | executing | emissions | resulting stack | + +-----------+---------------+--------------------------+ + | op 1 | 1a, 1b, 1c | 1a, 1b, 1c | + | op 1a | 1ai, 1aj | 1ai, 1aj, 1b, 1c | + | op 1ai | | 1aj, 1b, 1c | + | op 1aj | | 1b, 1c | + | op 1b | 1bi | 1bi, 1c | + | op 1bi | | 1c | + | op 1c | | | + | op 2 | 2a, 2b | 2a, 2b | + | op 2a | 2ai | 2ai, 2b | + | op 2ai | 2ai1 | 2ai1, 2b | + | op 2ai1 | | 2b | + | op 2b | 2bi | 2bi | + | op 2bi | 2bi1 | 2bi1 | + | op 2bi1 | 2bi2 | 2bi2 | + | op 2bi2 | | | + +-----------+---------------+--------------------------+ + +Failures +~~~~~~~~ + +All transactions can fail for a few reasons, mostly: + + - Not enough tokens in the source to spend the specified amount. + - The script took too many execution steps. + - The script failed programmatically using the ``FAILWITH`` instruction. + +External transactions can also fail for these additional reasons: + + - The signature of the external operations was wrong. + - The code or initial storage in an origination did not typecheck. + - The parameter in a transfer did not typecheck. + - The destination did not exist. + - The specified entrypoint did not exist. + +All these errors cannot happen in internal transactions, as the type +system catches them at operation creation time. In particular, +Michelson has two types to talk about other accounts: ``address`` and +``contract t``. The ``address`` type merely gives the guarantee that +the value has the form of a Tezos address. The ``contract t`` type, on +the other hand, guarantees that the value is indeed a valid, existing +account whose parameter type is ``t``. To make a transaction from +Michelson, a value of type ``contract t`` must be provided, and the +type system checks that the argument to the transaction is indeed of +type ``t``. Hence, all transactions made from Michelson are well +formed by construction. + +In any case, when a failure happens, either total success or total +failure is guaranteed. If a transaction (internal or external) fails, +then the whole sequence fails and all the effects up to the failure +are reverted. These transactions can still be included in blocks, and +the transaction fees given to the implicit account who baked the block. + +Language semantics +------------------ + +This specification explains in a symbolic way the computation performed by the +Michelson interpreter on a given program and initial stack to produce +the corresponding resulting stack. The Michelson interpreter is a pure +function: it only builds a result stack from the elements of an initial +one, without affecting its environment. This semantics is then naturally +given in what is called a big step form: a symbolic definition of a +recursive reference interpreter. This definition takes the form of a +list of rules that cover all the possible inputs of the interpreter +(program and stack), and describe the computation of the corresponding +resulting stacks. + +Rules form and selection +~~~~~~~~~~~~~~~~~~~~~~~~ + +The rules have the main following form. + +:: + + > (syntax pattern) / (initial stack pattern) => (result stack pattern) + iff (conditions) + where (recursions) + and (more recursions) + +The left hand side of the ``=>`` sign is used for selecting the rule. +Given a program and an initial stack, one (and only one) rule can be +selected using the following process. First, the toplevel structure of +the program must match the syntax pattern. This is quite simple since +there is only a few non trivial patterns to deal with instruction +sequences, and the rest is made of trivial pattern that match one +specific instruction. Then, the initial stack must match the initial +stack pattern. Finally, some rules add extra conditions over the values +in the stack that follow the ``iff`` keyword. Sometimes, several rules +may apply in a given context. In this case, the one that appears first +in this specification is to be selected. If no rule applies, the result +is equivalent to the one for the explicit ``FAILWITH`` instruction. This +case does not happen on well-typed programs, as explained in the next +section. + +The right hand side describes the result of the interpreter if the rule +applies. It consists in a stack pattern, whose parts are either +constants, or elements of the context (program and initial stack) that +have been named on the left hand side of the ``=>`` sign. + +Recursive rules (big step form) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes, the result of interpreting a program is derived from the +result of interpreting another one (as in conditionals or function +calls). In these cases, the rule contains a clause of the following +form. + +:: + + where (intermediate program) / (intermediate stack) => (partial result) + +This means that this rules applies in case interpreting the intermediate +state on the left gives the pattern on the right. + +The left hand sign of the ``=>`` sign is constructed from elements of +the initial state or other partial results, and the right hand side +identify parts that can be used to build the result stack of the rule. + +If the partial result pattern does not actually match the result of the +interpretation, then the result of the whole rule is equivalent to the +one for the explicit ``FAILWITH`` instruction. Again, this case does not +happen on well-typed programs, as explained in the next section. + +Format of patterns +~~~~~~~~~~~~~~~~~~ + +Code patterns are of one of the following syntactical forms. + +- ``INSTR`` (an uppercase identifier) is a simple instruction (e.g. + ``DROP``). +- ``INSTR (arg) ...`` is a compound instruction, whose arguments can be + code, data or type patterns (e.g. ``PUSH nat 3``). +- ``{ (instr) ; ... }`` is a possibly empty sequence of instructions, + (e.g. ``IF { SWAP ; DROP } { DROP }``), nested sequences can drop the + braces. +- ``name`` is a pattern that matches any program and names a part of + the matched program that can be used to build the result. +- ``_`` is a pattern that matches any instruction. + +Stack patterns are of one of the following syntactical forms. + +- ``[FAILED]`` is the special failed state. +- ``[]`` is the empty stack. +- ``(top) : (rest)`` is a stack whose top element is matched by the + data pattern ``(top)`` on the left, and whose remaining elements are + matched by the stack pattern ``(rest)`` on the right (e.g. + ``x : y : rest``). +- ``name`` is a pattern that matches any stack and names it in order to + use it to build the result. +- ``_`` is a pattern that matches any stack. + +Data patterns are of one of the following syntactical forms. + +- integer/natural number literals, (e.g. ``3``). +- string literals, (e.g. ``"contents"``). +- raw byte sequence literals (e.g. ``0xABCDEF42``). +- ``Tag`` (capitalized) is a symbolic constant, (e.g. ``Unit``, + ``True``, ``False``). +- ``(Tag (arg) ...)`` tagged constructed data, (e.g. ``(Pair 3 4)``). +- a code pattern for first class code values. +- ``name`` to name a value in order to use it to build the result. +- ``_`` to match any value. + +The domain of instruction names, symbolic constants and data +constructors is fixed by this specification. Michelson does not let the +programmer introduce its own types. + +Be aware that the syntax used in the specification may differ from +the :ref:`concrete syntax `. In particular +some instructions are annotated with types that are not present in the +concrete language because they are synthesized by the typechecker. + +Shortcuts +~~~~~~~~~ + +Sometimes, it is easier to think (and shorter to write) in terms of +program rewriting than in terms of big step semantics. When it is the +case, and when both are equivalents, we write rules of the form: + +:: + + p / S => S'' + where p' / S' => S'' + +using the following shortcut: + +:: + + p / S => p' / S' + +The concrete language also has some syntax sugar to group some common +sequences of operations as one. This is described in this specification +using a simple regular expression style recursive instruction rewriting. + +Introduction to the type system and notations +--------------------------------------------- + +This specification describes a type system for Michelson. To make things +clear, in particular to readers that are not accustomed to reading +formal programming language specifications, it does not give a +typechecking or inference algorithm. It only gives an intentional +definition of what we consider to be well-typed programs. For each +syntactical form, it describes the stacks that are considered well-typed +inputs, and the resulting outputs. + +The type system is sound, meaning that if a program can be given a type, +then if run on a well-typed input stack, the interpreter will never +apply an interpretation rule on a stack of unexpected length or +contents. Also, it will never reach a state where it cannot select an +appropriate rule to continue the execution. Well-typed programs do not +block, and do not go wrong. + +Type notations +~~~~~~~~~~~~~~ + +The specification introduces notations for the types of values, terms +and stacks. Apart from a subset of value types that appear in the form +of type annotations in some places throughout the language, it is +important to understand that this type language only exists in the +specification. + +A stack type can be written: + +- ``[]`` for the empty stack. +- ``(top) : (rest)`` for the stack whose first value has type ``(top)`` + and queue has stack type ``(rest)``. + +Instructions, programs and primitives of the language are also typed, +their types are written: + +:: + + (type of stack before) -> (type of stack after) + +The types of values in the stack are written: + +- ``identifier`` for a primitive data-type (e.g. ``bool``). +- ``identifier (arg)`` for a parametric data-type with one parameter + type ``(arg)`` (e.g. ``list nat``). +- ``identifier (arg) ...`` for a parametric data-type with several + parameters (e.g. ``map string int``). +- ``[ (type of stack before) -> (type of stack after) ]`` for a code + quotation, (e.g. ``[ int : int : [] -> int : [] ]``). +- ``lambda (arg) (ret)`` is a shortcut for + ``[ (arg) : [] -> (ret) : [] ]``. + +Meta type variables +~~~~~~~~~~~~~~~~~~~ + +The typing rules introduce meta type variables. To be clear, this has +nothing to do with polymorphism, which Michelson does not have. These +variables only live at the specification level, and are used to express +the consistency between the parts of the program. For instance, the +typing rule for the ``IF`` construct introduces meta variables to +express that both branches must have the same type. + +Here are the notations for meta type variables: + +- ``'a`` for a type variable. +- ``'A`` for a stack type variable. +- ``_`` for an anonymous type or stack type variable. + +Typing rules +~~~~~~~~~~~~ + +The system is syntax directed, meaning that it defines a single +typing rule for each syntax construct. A typing rule restricts the type +of input stacks that are authorized for this syntax construct, links the +output type to the input type, and links both of them to the +subexpressions when needed, using meta type variables. + +Typing rules are of the form: + +:: + + (syntax pattern) + :: (type of stack before) -> (type of stack after) [rule-name] + iff (premises) + +Where premises are typing requirements over subprograms or values in the +stack, both of the form ``(x) :: (type)``, meaning that value ``(x)`` +must have type ``(type)``. + +A program is shown well-typed if one can find an instance of a rule that +applies to the toplevel program expression, with all meta type variables +replaced by non variable type expressions, and of which all type +requirements in the premises can be proven well-typed in the same +manner. For the reader unfamiliar with formal type systems, this is +called building a typing derivation. + +Here is an example typing derivation on a small program that computes +``(x+5)*10`` for a given input ``x``, obtained by instantiating the +typing rules for instructions ``PUSH``, ``ADD`` and for the sequence, as +found in the next sections. When instantiating, we replace the ``iff`` +with ``by``. + +:: + + { PUSH nat 5 ; ADD ; PUSH nat 10 ; MUL } + :: [ nat : [] -> nat : [] ] + by { PUSH nat 5 ; ADD } + :: [ nat : [] -> nat : [] ] + by PUSH nat 5 + :: [ nat : [] -> nat : nat : [] ] + by 5 :: nat + and ADD + :: [ nat : nat : [] -> nat : [] ] + and { PUSH nat 10 ; MUL } + :: [ nat : [] -> nat : [] ] + by PUSH nat 10 + :: [ nat : [] -> nat : nat : [] ] + by 10 :: nat + and MUL + :: [ nat : nat : [] -> nat : [] ] + +Producing such a typing derivation can be done in a number of manners, +such as unification or abstract interpretation. In the implementation of +Michelson, this is done by performing a recursive symbolic evaluation of +the program on an abstract stack representing the input type provided by +the programmer, and checking that the resulting symbolic stack is +consistent with the expected result, also provided by the programmer. + +Side note +~~~~~~~~~ + +As with most type systems, it is incomplete. There are programs that +cannot be given a type in this type system, yet that would not go wrong +if executed. This is a necessary compromise to make the type system +usable. Also, it is important to remember that the implementation of +Michelson does not accept as many programs as the type system describes +as well-typed. This is because the implementation uses a simple single +pass typechecking algorithm, and does not handle any form of +polymorphism. + +Core data types and notations +----------------------------- + +- ``string``, ``nat``, ``int`` and ``bytes``: The core primitive + constant types. + +- ``bool``: The type for booleans whose values are ``True`` and + ``False``. + +- ``unit``: The type whose only value is ``Unit``, to use as a + placeholder when some result or parameter is not necessary. For + instance, when the only goal of a contract is to update its storage. + +- ``never``: The empty type. Since ``never`` has no inhabitant, no value of + this type is allowed to occur in a well-typed program. + +- ``list (t)``: A single, immutable, homogeneous linked list, whose + elements are of type ``(t)``, and that we write ``{}`` for the empty + list or ``{ first ; ... }``. In the semantics, we use chevrons to + denote a subsequence of elements. For instance: ``{ head ; }``. + +- ``pair (l) (r)``: A pair of values ``a`` and ``b`` of types ``(l)`` + and ``(r)``, that we write ``(Pair a b)``. + +- ``pair (t{1}) ... (t{n})`` with ``n > 2``: A shorthand for ``pair (t{1}) (pair (t{2}) ... (pair (t{n-1}) (t{n})) ...)``. + +- ``option (t)``: Optional value of type ``(t)`` that we write ``None`` + or ``(Some v)``. + +- ``or (l) (r)``: A union of two types: a value holding either a value + ``a`` of type ``(l)`` or a value ``b`` of type ``(r)``, that we write + ``(Left a)`` or ``(Right b)``. + +- ``set (t)``: Immutable sets of values of type ``(t)`` that we write as + lists ``{ item ; ... }``, of course with their elements unique, and + sorted. + +- ``map (k) (t)``: Immutable maps from keys of type ``(k)`` of values + of type ``(t)`` that we write ``{ Elt key value ; ... }``, with keys + sorted. + +- ``big_map (k) (t)``: Lazily deserialized maps from keys of type + ``(k)`` of values of type ``(t)``. These maps should be used if one + intends to store large amounts of data in a map. They have higher + gas costs than standard maps as data is lazily deserialized. A + ``big_map`` cannot appear inside another ``big_map``. See the + section on :ref:`operations on big maps ` + for a description of the syntax of values of type ``big_map (k) + (t)`` and available operations. + +Core instructions +----------------- + +Control structures +~~~~~~~~~~~~~~~~~~ + +- ``FAILWITH``: Explicitly abort the current program. + +:: + + :: 'a : \_ -> \_ + +This special instruction aborts the current program exposing the top +element of the stack in its error message (first rule below). It makes +the output useless since all subsequent instructions will simply +ignore their usual semantics to propagate the failure up to the main +result (second rule below). Its type is thus completely generic. + +:: + + > FAILWITH / a : _ => [FAILED] + > _ / [FAILED] => [FAILED] + +- ``{}``: Empty sequence. + +:: + + :: 'A -> 'A + + > {} / SA => SA + +- ``{ I ; C }``: Sequence. + +:: + + :: 'A -> 'C + iff I :: [ 'A -> 'B ] + C :: [ 'B -> 'C ] + + > I ; C / SA => SC + where I / SA => SB + and C / SB => SC + +- ``IF bt bf``: Conditional branching. + +:: + + :: bool : 'A -> 'B + iff bt :: [ 'A -> 'B ] + bf :: [ 'A -> 'B ] + + > IF bt bf / True : S => bt / S + > IF bt bf / False : S => bf / S + +- ``LOOP body``: A generic loop. + +:: + + :: bool : 'A -> 'A + iff body :: [ 'A -> bool : 'A ] + + > LOOP body / True : S => body ; LOOP body / S + > LOOP body / False : S => S + +- ``LOOP_LEFT body``: A loop with an accumulator. + +:: + + :: (or 'a 'b) : 'A -> 'b : 'A + iff body :: [ 'a : 'A -> (or 'a 'b) : 'A ] + + > LOOP_LEFT body / (Left a) : S => body ; LOOP_LEFT body / a : S + > LOOP_LEFT body / (Right b) : S => b : S + +- ``DIP code``: Runs code protecting the top element of the stack. + +:: + + :: 'b : 'A -> 'b : 'C + iff code :: [ 'A -> 'C ] + + > DIP code / x : S => x : S' + where code / S => S' + +- ``DIP n code``: Runs code protecting the ``n`` topmost elements of + the stack. In particular, ``DIP 0 code`` is equivalent to ``code`` + and ``DIP 1 code`` is equivalent to ``DIP code``. + +:: + + :: 'a{1} : ... : 'a{n} : 'A -> 'a{1} : ... : 'a{n} : 'B + iff code :: [ 'A -> 'B ] + + > DIP n code / x{1} : ... : x{n} : S => x{1} : ... : x{n} : S' + where code / S => S' + +- ``EXEC``: Execute a function from the stack. + +:: + + :: 'a : lambda 'a 'b : 'C -> 'b : 'C + + > EXEC / a : f : S => r : S + where f / a : [] => r : [] + +- ``APPLY``: Partially apply a tuplified function from the stack. + Values that are not both pushable and storable + (values of type ``operation``, ``contract _`` and ``big map _ _``) + cannot be captured by ``APPLY`` (cannot appear in ``'a``). + +:: + + :: 'a : lambda (pair 'a 'b) 'c : 'C -> lambda 'b 'c : 'C + + > APPLY / a : f : S => { PUSH 'a a ; PAIR ; f } : S + +Stack operations +~~~~~~~~~~~~~~~~ + +- ``DROP``: Drop the top element of the stack. + +:: + + :: _ : 'A -> 'A + + > DROP / _ : S => S + +- ``DROP n``: Drop the `n` topmost elements of the stack. In + particular, ``DROP 0`` is a noop and ``DROP 1`` is equivalent to + ``DROP``. + +:: + + :: 'a{1} : ... : 'a{n} : 'A -> 'A + + > DROP n / x{1} : ... : x{n} : S => S + +- ``DUP``: Duplicate the top element of the stack. + +:: + + :: 'a : 'A -> 'a : 'a : 'A + + > DUP / x : S => x : x : S + +- ``DUP n``: Duplicate the N-th element of the stack. `DUP 1` is equivalent to `DUP`. `DUP 0` is rejected. + +:: + + DUP 1 :: 'a : 'A -> 'a : 'a : 'A + + DUP (n+1) :: 'a : 'A -> 'b : 'a : 'A + iff DUP n :: 'A -> 'b : 'A + + > DUP 1 / x : S => x : x : S + + > DUP (n+1) / x : S => y : x : S + iff DUP n / S => y : S + + +- ``SWAP``: Exchange the top two elements of the stack. + +:: + + :: 'a : 'b : 'A -> 'b : 'a : 'A + + > SWAP / x : y : S => y : x : S + +- ``DIG n``: Take the element at depth ``n`` of the stack and move it + on top. The element on top of the stack is at depth ``0`` so that + ``DIG 0`` is a no-op and ``DIG 1`` is equivalent to ``SWAP``. + +:: + + :: 'a{1} : ... : 'a{n} : 'b : 'A -> 'b : 'a{1} : ... : 'a{n} : 'A + + > DIG n / x{1} : ... : x{n} : y : S => y : x{1} : ... : x{n} : S + +- ``DUG n``: Place the element on top of the stack at depth ``n``. The + element on top of the stack is at depth ``0`` so that ``DUG 0`` is a + no-op and ``DUG 1`` is equivalent to ``SWAP``. + +:: + + :: 'b : 'a{1} : ... : 'a{n} : 'A -> 'a{1} : ... : 'a{n} : 'b : 'A + + > DUG n / y : x{1} : ... : x{n} : S => x{1} : ... : x{n} : y : S + +- ``PUSH 'a x``: Push a constant value of a given type onto the stack. + +:: + + :: 'A -> 'a : 'A + iff x :: 'a + + > PUSH 'a x / S => x : S + +- ``LAMBDA 'a 'b code``: Push a lambda with the given parameter type `'a` and return + type `'b` onto the stack. + +:: + + :: 'A -> (lambda 'a 'b) : 'A + + > LAMBDA _ _ code / S => code : S + +Generic comparison +~~~~~~~~~~~~~~~~~~ + +Comparison only works on a class of types that we call comparable. A +``COMPARE`` operation is defined in an ad hoc way for each comparable +type, but the result of compare is always an ``int``, which can in turn +be checked in a generic manner using the following combinators. The +result of ``COMPARE`` is ``0`` if the top two elements of the stack are +equal, negative if the first element in the stack is less than the +second, and positive otherwise. + +- ``EQ``: Checks that the top element of the stack is equal to zero. + +:: + + :: int : 'S -> bool : 'S + + > EQ / 0 : S => True : S + > EQ / v : S => False : S + iff v <> 0 + +- ``NEQ``: Checks that the top element of the stack is not equal to zero. + +:: + + :: int : 'S -> bool : 'S + + > NEQ / 0 : S => False : S + > NEQ / v : S => True : S + iff v <> 0 + +- ``LT``: Checks that the top element of the stack is less than zero. + +:: + + :: int : 'S -> bool : 'S + + > LT / v : S => True : S + iff v < 0 + > LT / v : S => False : S + iff v >= 0 + +- ``GT``: Checks that the top element of the stack is greater than zero. + +:: + + :: int : 'S -> bool : 'S + + > GT / v : S => C / True : S + iff v > 0 + > GT / v : S => C / False : S + iff v <= 0 + +- ``LE``: Checks that the top element of the stack is less than or equal to + zero. + +:: + + :: int : 'S -> bool : 'S + + > LE / v : S => True : S + iff v <= 0 + > LE / v : S => False : S + iff v > 0 + +- ``GE``: Checks that the top of the stack is greater than or equal to + zero. + +:: + + :: int : 'S -> bool : 'S + + > GE / v : S => True : S + iff v >= 0 + > GE / v : S => False : S + iff v < 0 + +Operations +---------- + +Operations on unit +~~~~~~~~~~~~~~~~~~ + +- ``UNIT``: Push a unit value onto the stack. + +:: + + :: 'A -> unit : 'A + + > UNIT / S => Unit : S + +- ``COMPARE``: Unit comparison + +:: + + :: unit : unit : 'S -> int : 'S + + > COMPARE / Unit : Unit : S => 0 : S + +Operations on type never +~~~~~~~~~~~~~~~~~~~~~~~~ + +The type ``never`` is the type of forbidden values. The most prominent +scenario in which ``never`` is used is when implementing a contract +template with no additional entrypoint. A contract template defines a set +of basic entrypoints, and its ``parameter`` declaration contains a type +variable for additional entrypoints in some branch of an union type, or +wrapped inside an option type. Letting this type variable be ``never`` in +a particular implementation indicates that the contract template has not +been extended, and turns the branch in the code that processes the +additional entrypoints into a forbidden branch. + +Values of type ``never`` cannot occur in a well-typed program. However, +they can be abstracted in the ``parameter`` declaration of a contract---or +by using the ``LAMBDA`` operation---thus indicating that the corresponding +branches in the code are forbidden. The type ``never`` also plays a role +when introducing values of union or option type with ``LEFT never``, +``RIGHT never``, or ``NONE never``. In such cases, the created values can +be inspected with the operations ``IF_LEFT``, ``IF_RIGHT``, or +``IF_NONE``, and the corresponding branches in the code are forbidden +branches. + +- ``NEVER``: Close a forbidden branch. + +:: + :: never : 'A -> 'B + +- ``COMPARE``: Trivial comparison on type ``never`` + +:: + + :: never : never : 'S -> int : 'S + + +Operations on booleans +~~~~~~~~~~~~~~~~~~~~~~ + +- ``OR`` + +:: + + :: bool : bool : 'S -> bool : 'S + + > OR / x : y : S => (x | y) : S + +- ``AND`` + +:: + + :: bool : bool : 'S -> bool : 'S + + > AND / x : y : S => (x & y) : S + +- ``XOR`` + +:: + + :: bool : bool : 'S -> bool : 'S + + > XOR / x : y : S => (x ^ y) : S + +- ``NOT`` + +:: + + :: bool : 'S -> bool : 'S + + > NOT / x : S => ~x : S + +- ``COMPARE``: Boolean comparison + +:: + + :: bool : bool : 'S -> int : 'S + + > COMPARE / False : False : S => 0 : S + > COMPARE / False : True : S => -1 : S + > COMPARE / True : False : S => 1 : S + > COMPARE / True : True : S => 0 : S + +Operations on integers and natural numbers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Integers and naturals are arbitrary-precision, meaning that the only size +limit is gas. + +- ``NEG`` + +:: + + :: int : 'S -> int : 'S + :: nat : 'S -> int : 'S + + > NEG / x : S => -x : S + +- ``ABS`` + +:: + + :: int : 'S -> nat : 'S + + > ABS / x : S => abs (x) : S + +- ``ISNAT`` + +:: + + :: int : 'S -> option nat : 'S + + > ISNAT / x : S => Some (x) : S + iff x >= 0 + + > ISNAT / x : S => None : S + iff x < 0 + +- ``INT`` + +:: + + :: nat : 'S -> int : 'S + + > INT / x : S => x : S + +- ``ADD`` + +:: + + :: int : int : 'S -> int : 'S + :: int : nat : 'S -> int : 'S + :: nat : int : 'S -> int : 'S + :: nat : nat : 'S -> nat : 'S + + > ADD / x : y : S => (x + y) : S + +- ``SUB`` + +:: + + :: int : int : 'S -> int : 'S + :: int : nat : 'S -> int : 'S + :: nat : int : 'S -> int : 'S + :: nat : nat : 'S -> int : 'S + + > SUB / x : y : S => (x - y) : S + +- ``MUL`` + +:: + + :: int : int : 'S -> int : 'S + :: int : nat : 'S -> int : 'S + :: nat : int : 'S -> int : 'S + :: nat : nat : 'S -> nat : 'S + + > MUL / x : y : S => (x * y) : S + +- ``EDIV``: Perform Euclidean division + +:: + + :: int : int : 'S -> option (pair int nat) : 'S + :: int : nat : 'S -> option (pair int nat) : 'S + :: nat : int : 'S -> option (pair int nat) : 'S + :: nat : nat : 'S -> option (pair nat nat) : 'S + + > EDIV / x : 0 : S => None : S + > EDIV / x : y : S => Some (Pair (x / y) (x % y)) : S + iff y <> 0 + +Bitwise logical operators are also available on unsigned integers. + +- ``OR`` + +:: + + :: nat : nat : 'S -> nat : 'S + + > OR / x : y : S => (x | y) : S + +- ``AND``: (also available when the top operand is signed) + +:: + + :: nat : nat : 'S -> nat : 'S + :: int : nat : 'S -> nat : 'S + + > AND / x : y : S => (x & y) : S + +- ``XOR`` + +:: + + :: nat : nat : 'S -> nat : 'S + + > XOR / x : y : S => (x ^ y) : S + +- ``NOT``: Two's complement + +:: + + :: nat : 'S -> int : 'S + :: int : 'S -> int : 'S + + > NOT / x : S => ~x : S + + +The return type of ``NOT`` is an ``int`` and not a ``nat``. This is +because the sign is also negated. The resulting integer is computed +using two's complement. For instance, the boolean negation of ``0`` is +``-1``. To get a natural back, a possibility is to use ``AND`` with an +unsigned mask afterwards. + + +- ``LSL`` + +:: + + :: nat : nat : 'S -> nat : 'S + + > LSL / x : s : S => (x << s) : S + iff s <= 256 + > LSL / x : s : S => [FAILED] + iff s > 256 + +- ``LSR`` + +:: + + :: nat : nat : 'S -> nat : 'S + + > LSR / x : s : S => (x >> s) : S + iff s <= 256 + > LSR / x : s : S => [FAILED] + iff s > 256 + +- ``COMPARE``: Integer/natural comparison + +:: + + :: int : int : 'S -> int : 'S + :: nat : nat : 'S -> int : 'S + + > COMPARE / x : y : S => -1 : S + iff x < y + > COMPARE / x : y : S => 0 : S + iff x = y + > COMPARE / x : y : S => 1 : S + iff x > y + +Operations on strings +~~~~~~~~~~~~~~~~~~~~~ + +Strings are mostly used for naming things without having to rely on +external ID databases. They are restricted to the printable subset of +7-bit ASCII, plus some escaped characters (see section on +constants). So what can be done is basically use string constants as +is, concatenate or splice them, and use them as keys. + + +- ``CONCAT``: String concatenation. + +:: + + :: string : string : 'S -> string : 'S + + > CONCAT / s : t : S => (s ^ t) : S + + :: string list : 'S -> string : 'S + + > CONCAT / {} : S => "" : S + > CONCAT / { s ; } : S => (s ^ r) : S + where CONCAT / { } : S => r : S + +- ``SIZE``: number of characters in a string. + +:: + + :: string : 'S -> nat : 'S + +- ``SLICE``: String access. + +:: + + :: nat : nat : string : 'S -> option string : 'S + + > SLICE / offset : length : s : S => Some ss : S + where ss is the substring of s at the given offset and of the given length + iff offset and (offset + length) are in bounds + > SLICE / offset : length : s : S => None : S + iff offset or (offset + length) are out of bounds + +- ``COMPARE``: Lexicographic comparison. + +:: + + :: string : string : 'S -> int : 'S + + > COMPARE / s : t : S => -1 : S + iff s < t + > COMPARE / s : t : S => 0 : S + iff s = t + > COMPARE / s : t : S => 1 : S + iff s > t + +Operations on pairs and right combs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The type ``pair l r`` is the type of binary pairs composed of a left +element of type ``l`` and a right element of type ``r``. A value of +type ``pair l r`` is written ``Pair x y`` where ``x`` is a value of +type ``l`` and ``y`` is a value of type ``r``. + +To build tuples of length greater than 2, right combs have specific +optimized operations. For any ``n > 2``, the compact notations ``pair +t{0} t{1} ... t{n-2} t{n-1}`` is provided for the type of right combs +``pair t{0} (pair t{1} ... (pair t{n-2} t{n-1}) ...)``. Similarly, the +compact notation ``Pair x{0} x{1} ... x{n-2} x{n-1}`` is provided for +the right-comb value ``Pair x{0} (Pair x{1} ... (Pair x{n-2} x{n-1}) +...)``. Right-comb values can also be written using sequences; ``Pair +x{0} x{1} ... x{n-2} x{n-1}`` can be written ``{x{0}; x{1}; ...; x{n-2}; x{n-1}}``. + +- ``PAIR``: Build a binary pair from the stack's top two elements. + +:: + + :: 'a : 'b : 'S -> pair 'a 'b : 'S + + > PAIR / x : y : S => Pair x y : S + +- ``PAIR n``: Fold ``n`` values on the top of the stack in a right comb. + ``PAIR 0`` and ``PAIR 1`` are rejected. ``PAIR 2`` is equivalent to ``PAIR``. + +:: + + PAIR 2 :: 'a : 'b : 'S -> pair 'a 'b : 'S + PAIR (k+1) :: 'x : 'S -> pair 'x 'y : 'T + iff PAIR k :: 'S -> 'y : 'T + + Or equivalently, for n >= 2, + PAIR n :: 'a{0} : ... : 'a{n-1} : 'A -> pair 'a{0} ... 'a{n-1} : 'A + + > PAIR 2 / x : y : S => Pair x y : S + > PAIR (k+1) / x : S => Pair x y : T + iff PAIR k / S => y : T + + Or equivalently, for n >= 2, + > PAIR n / x{0} : ... : x{n-1} : S => Pair x{0} ... x{n-1} : S + +- ``UNPAIR``: Split a pair into its components. + +:: + + :: pair 'a 'b : 'S -> 'a : 'b : 'S + + > UNPAIR / Pair a b : S => a : b : S + + +- ``UNPAIR n``: Unfold ``n`` values from a right comb on the top of the stack. ``UNPAIR 0`` and ``UNPAIR 1`` are rejected. ``UNPAIR 2`` is equivalent to ``UNPAIR``. + +:: + + UNPAIR 2 :: pair 'a 'b : 'A -> 'a : 'b : 'A + UNPAIR (k+1) :: pair 'a 'b : 'A -> 'a : 'B + iff UNPAIR k :: 'b : 'A -> 'B + + Or equivalently, for n >= 2, + UNPAIR n :: pair 'a{0} ... 'a{n-1} : S -> 'a{0} : ... : 'a{n-1} : S + + > UNPAIR 2 / Pair x y : S => x : y : S + > UNPAIR (k+1) / Pair x y : SA => x : SB + iff UNPAIR k / y : SA => SB + + Or equivalently, for n >= 2, + > UNPAIR n / Pair x{0} ... x{n-1} : S => x{0} : ... : x{n-1} : S + +- ``CAR``: Access the left part of a pair. + +:: + + :: pair 'a _ : 'S -> 'a : 'S + + > CAR / Pair x _ : S => x : S + +- ``CDR``: Access the right part of a pair. + +:: + + :: pair _ 'b : 'S -> 'b : 'S + + > CDR / Pair _ y : S => y : S + +- ``GET k``: Access an element or a sub comb in a right comb. + + The nodes of a right comb of size ``n`` are canonically numbered as follows: + +:: + + 0 + / \ + 1 2 + / \ + 3 4 + / \ + 5 ... + 2n-2 + / \ + 2n-1 2n + + +Or in plain English: + + - The root is numbered with 0, + - The left child of the node numbered by ``k`` is numbered by ``k+1``, and + - The right child of the node numbered by ``k`` is numbered by ``k+2``. + +The ``GET k`` instruction accesses the node numbered by ``k``. In +particular, for a comb of size ``n``, the ``n-1`` first elements are +accessed by ``GET 1``, ``GET 3``, ..., and ``GET (2n-1)`` and the last +element is accessed by ``GET (2n)``. + +:: + + GET 0 :: 'a : 'S -> 'a : 'S + GET 1 :: pair 'x _ : 'S -> 'x : 'S + GET (k+2) :: pair _ 'y : 'S -> 'z : 'S + iff GET k :: 'y : 'S -> 'z : 'S + + Or equivalently, + GET 0 :: 'a : 'S -> 'a : 'S + GET (2k) :: pair 'a{0} ... 'a{k-1} 'a{k} : 'S -> 'a{k} : 'S + GET (2k+1) :: pair 'a{0} ... 'a{k} 'a{k+1} : 'S -> 'a{k} : 'S + + > GET 0 / x : S => x : S + > GET 1 / Pair x _ : S => x : S + > GET (k+2) / Pair _ y : S => GET k / y : S + + Or equivalently, + > GET 0 / x : S => x : S + > GET (2k) / Pair x{0} ... x{k-1} x{k} : 'S -> x{k} : 'S + > GET (2k+1) / Pair x{0} ... x{k} x{k+1} : 'S -> x{k} : 'S + + +- ``UPDATE k``: Update an element or a sub comb in a right comb. The topmost stack element is the new value to insert in the comb, the second stack element is the right comb to update. The meaning of ``k`` is the same as for the ``GET k`` instruction. + +:: + + UPDATE 0 :: 'a : 'b : 'S -> 'a : 'S + UPDATE 1 :: 'a2 : pair 'a1 'b : 'S -> pair 'a2 'b : 'S + UPDATE (k+2) :: 'c : pair 'a 'b1 : 'S -> pair 'a 'b2 : 'S + iff UPDATE k :: 'c : 'b1 : 'S -> 'b2 : 'S + + Or equivalently, + UPDATE 0 :: 'a : 'b : 'S -> 'a : 'S + UPDATE (2k) :: 'c : pair 'a{0} ... 'a{k-1} 'a{k} : 'S -> pair 'a{0} ... 'a{k-1} 'c : 'S + UPDATE (2k+1) :: 'c : pair 'a{0} ... 'a{k} 'a{k+1} : 'S -> pair 'a{0} ... 'a{k-1} 'c 'a{k+1} : 'S + + > UPDATE 0 / x : _ : S => x : S + > UPDATE 1 / x2 : Pair x1 y : S => Pair x2 y : S + > UPDATE (k+2) / z : Pair x y1 : S => Pair x y2 : S + iff UPDATE k / z : y1 : S => y2 : S + + Or equivalently, + > UPDATE 0 / x : _ : S => x : S + > UPDATE (2k) / z : Pair x{0} ... x{k-1} x{k} : 'S => Pair x{0} ... x{k-1} z : 'S + > UPDATE (2k+1) / z : Pair x{0} ... x{k-1} x{k} x{k+1} : 'S => Pair x{0} ... x{k-1} z x{k+1} : 'S + +- ``COMPARE``: Lexicographic comparison. + +:: + + :: pair 'a 'b : pair 'a 'b : 'S -> int : 'S + + > COMPARE / (Pair sa sb) : (Pair ta tb) : S => -1 : S + iff COMPARE / sa : ta : S => -1 : S + > COMPARE / (Pair sa sb) : (Pair ta tb) : S => 1 : S + iff COMPARE / sa : ta : S => 1 : S + > COMPARE / (Pair sa sb) : (Pair ta tb) : S => r : S + iff COMPARE / sa : ta : S => 0 : S + COMPARE / sb : tb : S => r : S + +Operations on sets +~~~~~~~~~~~~~~~~~~ + +- ``EMPTY_SET 'elt``: Build a new, empty set for elements of a given + type. + + The ``'elt`` type must be comparable (the ``COMPARE`` + primitive must be defined over it). + +:: + + :: 'S -> set 'elt : 'S + + > EMPTY_SET _ / S => {} : S + +- ``MEM``: Check for the presence of an element in a set. + +:: + + :: 'elt : set 'elt : 'S -> bool : 'S + + > MEM / x : {} : S => false : S + > MEM / x : { hd ; } : S => r : S + iff COMPARE / x : hd : [] => 1 : [] + where MEM / x : { } : S => r : S + > MEM / x : { hd ; } : S => true : S + iff COMPARE / x : hd : [] => 0 : [] + > MEM / x : { hd ; } : S => false : S + iff COMPARE / x : hd : [] => -1 : [] + +- ``UPDATE``: Inserts or removes an element in a set, replacing a + previous value. + +:: + + :: 'elt : bool : set 'elt : 'S -> set 'elt : 'S + + > UPDATE / x : false : {} : S => {} : S + > UPDATE / x : true : {} : S => { x } : S + > UPDATE / x : v : { hd ; } : S => { hd ; } : S + iff COMPARE / x : hd : [] => 1 : [] + where UPDATE / x : v : { } : S => { } : S + > UPDATE / x : false : { hd ; } : S => { } : S + iff COMPARE / x : hd : [] => 0 : [] + > UPDATE / x : true : { hd ; } : S => { hd ; } : S + iff COMPARE / x : hd : [] => 0 : [] + > UPDATE / x : false : { hd ; } : S => { hd ; } : S + iff COMPARE / x : hd : [] => -1 : [] + > UPDATE / x : true : { hd ; } : S => { x ; hd ; } : S + iff COMPARE / x : hd : [] => -1 : [] + +- ``ITER body``: Apply the body expression to each element of a set. + The body sequence has access to the stack. + +:: + + :: (set 'elt) : 'A -> 'A + iff body :: [ 'elt : 'A -> 'A ] + + > ITER body / {} : S => S + > ITER body / { hd ; } : S => ITER body / { } : S' + iff body / hd : S => S' + + +- ``SIZE``: Get the cardinality of the set. + +:: + + :: set 'elt : 'S -> nat : 'S + + > SIZE / {} : S => 0 : S + > SIZE / { _ ; } : S => 1 + s : S + where SIZE / { } : S => s : S + +Operations on maps +~~~~~~~~~~~~~~~~~~ + +- ``EMPTY_MAP 'key 'val``: Build a new, empty map from keys of a + given type to values of another given type. + + The ``'key`` type must be comparable (the ``COMPARE`` primitive must + be defined over it). + +:: + + :: 'S -> map 'key 'val : 'S + + > EMPTY_MAP _ _ / S => {} : S + + +- ``GET``: Access an element in a map, returns an optional value to be + checked with ``IF_SOME``. + +:: + + :: 'key : map 'key 'val : 'S -> option 'val : 'S + + > GET / x : {} : S => None : S + > GET / x : { Elt k v ; } : S => opt_y : S + iff COMPARE / x : k : [] => 1 : [] + where GET / x : { } : S => opt_y : S + > GET / x : { Elt k v ; } : S => Some v : S + iff COMPARE / x : k : [] => 0 : [] + > GET / x : { Elt k v ; } : S => None : S + iff COMPARE / x : k : [] => -1 : [] + +- ``MEM``: Check for the presence of a binding for a key in a map. + +:: + + :: 'key : map 'key 'val : 'S -> bool : 'S + + > MEM / x : {} : S => false : S + > MEM / x : { Elt k v ; } : S => r : S + iff COMPARE / x : k : [] => 1 : [] + where MEM / x : { } : S => r : S + > MEM / x : { Elt k v ; } : S => true : S + iff COMPARE / x : k : [] => 0 : [] + > MEM / x : { Elt k v ; } : S => false : S + iff COMPARE / x : k : [] => -1 : [] + +- ``UPDATE``: Assign or remove an element in a map. + +:: + + :: 'key : option 'val : map 'key 'val : 'S -> map 'key 'val : 'S + + > UPDATE / x : None : {} : S => {} : S + > UPDATE / x : Some y : {} : S => { Elt x y } : S + > UPDATE / x : opt_y : { Elt k v ; } : S => { Elt k v ; } : S + iff COMPARE / x : k : [] => 1 : [] + where UPDATE / x : opt_y : { } : S => { } : S + > UPDATE / x : None : { Elt k v ; } : S => { } : S + iff COMPARE / x : k : [] => 0 : [] + > UPDATE / x : Some y : { Elt k v ; } : S => { Elt k y ; } : S + iff COMPARE / x : k : [] => 0 : [] + > UPDATE / x : None : { Elt k v ; } : S => { Elt k v ; } : S + iff COMPARE / x : k : [] => -1 : [] + > UPDATE / x : Some y : { Elt k v ; } : S => { Elt x y ; Elt k v ; } : S + iff COMPARE / x : k : [] => -1 : [] + +- ``GET_AND_UPDATE``: A combination of the ``GET`` and ``UPDATE`` instructions. + +:: + + :: 'key : option 'val : map 'key 'val : 'S -> option 'val : map 'key 'val : 'S + +This instruction is similar to ``UPDATE`` but it also returns the +value that was previously stored in the ``map`` at the same key as +``GET`` would. + +:: + + > GET_AND_UPDATE / x : None : {} : S => None : {} : S + > GET_AND_UPDATE / x : Some y : {} : S => None : { Elt x y } : S + > GET_AND_UPDATE / x : opt_y : { Elt k v ; } : S => opt_y' : { Elt k v ; } : S + iff COMPARE / x : k : [] => 1 : [] + where GET_AND_UPDATE / x : opt_y : { } : S => opt_y' : { } : S + > GET_AND_UPDATE / x : None : { Elt k v ; } : S => Some v : { } : S + iff COMPARE / x : k : [] => 0 : [] + > GET_AND_UPDATE / x : Some y : { Elt k v ; } : S => Some v : { Elt k y ; } : S + iff COMPARE / x : k : [] => 0 : [] + > GET_AND_UPDATE / x : None : { Elt k v ; } : S => None : { Elt k v ; } : S + iff COMPARE / x : k : [] => -1 : [] + > GET_AND_UPDATE / x : Some y : { Elt k v ; } : S => None : { Elt x y ; Elt k v ; } : S + iff COMPARE / x : k : [] => -1 : [] + +- ``MAP body``: Apply the body expression to each element of a map. The + body sequence has access to the stack. + +:: + + :: (map 'key 'val) : 'A -> (map 'key 'b) : 'A + iff body :: [ (pair 'key 'val) : 'A -> 'b : 'A ] + + > MAP body / {} : S => {} : S + > MAP body / { Elt k v ; } : S => { Elt k v' ; } : S'' + where body / Pair k v : S => v' : S' + and MAP body / { } : S' => { } : S'' + +- ``ITER body``: Apply the body expression to each element of a map. + The body sequence has access to the stack. + +:: + + :: (map 'elt 'val) : 'A -> 'A + iff body :: [ (pair 'elt 'val : 'A) -> 'A ] + + > ITER body / {} : S => S + > ITER body / { Elt k v ; } : S => ITER body / { } : S' + iff body / (Pair k v) : S => S' + +- ``SIZE``: Get the cardinality of the map. + +:: + + :: map 'key 'val : 'S -> nat : 'S + + > SIZE / {} : S => 0 : S + > SIZE / { _ ; } : S => 1 + s : S + where SIZE / { } : S => s : S + + +Operations on ``big_maps`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. _OperationsOnBigMaps_009: + +Big maps have three possible representations. A map literal is always +a valid representation for a big map. Big maps can also be represented +by integers called big-map identifiers. Finally, big maps can be +represented as pairs of a big-map identifier (an integer) and a +big-map diff (written in the same syntax as a map whose values are +options). + +So for example, ``{ Elt "bar" True ; Elt "foo" False }``, ``42``, and +``Pair 42 { Elt "foo" (Some False) }`` are all valid representations +of type ``big_map string bool``. + +The behavior of big-map operations is the same as if they were normal +maps, except that under the hood, the elements are loaded and +deserialized on demand. + +- ``EMPTY_BIG_MAP 'key 'val``: Build a new, empty big map from keys of a + given type to values of another given type. + + The ``'key`` type must be comparable (the ``COMPARE`` primitive must + be defined over it). + +:: + + :: 'S -> map 'key 'val : 'S + +- ``GET``: Access an element in a ``big_map``, returns an optional value to be + checked with ``IF_SOME``. + +:: + + :: 'key : big_map 'key 'val : 'S -> option 'val : 'S + +- ``MEM``: Check for the presence of an element in a ``big_map``. + +:: + + :: 'key : big_map 'key 'val : 'S -> bool : 'S + +- ``UPDATE``: Assign or remove an element in a ``big_map``. + +:: + + :: 'key : option 'val : big_map 'key 'val : 'S -> big_map 'key 'val : 'S + + +- ``GET_AND_UPDATE``: A combination of the ``GET`` and ``UPDATE`` instructions. + +:: + + :: 'key : option 'val : big_map 'key 'val : 'S -> option 'val : big_map 'key 'val : 'S + +This instruction is similar to ``UPDATE`` but it also returns the +value that was previously stored in the ``big_map`` at the same key as +``GET`` would. + + +Operations on optional values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ``SOME``: Pack a value as an optional value. + +:: + + :: 'a : 'S -> option 'a : 'S + + > SOME / v : S => (Some v) : S + +- ``NONE 'a``: The absent optional value. + +:: + + :: 'S -> option 'a : 'S + + > NONE / S => None : S + +- ``IF_NONE bt bf``: Inspect an optional value. + +:: + + :: option 'a : 'A -> 'B + iff bt :: [ 'A -> 'B] + bf :: [ 'a : 'A -> 'B] + + > IF_NONE bt bf / (None) : S => bt / S + > IF_NONE bt bf / (Some a) : S => bf / a : S + +- ``COMPARE``: Optional values comparison + +:: + + :: option 'a : option 'a : 'S -> int : 'S + + > COMPARE / None : None : S => 0 : S + > COMPARE / None : (Some _) : S => -1 : S + > COMPARE / (Some _) : None : S => 1 : S + > COMPARE / (Some a) : (Some b) : S => COMPARE / a : b : S + +Operations on unions +~~~~~~~~~~~~~~~~~~~~ + +- ``LEFT 'b``: Pack a value in a union (left case). + +:: + + :: 'a : 'S -> or 'a 'b : 'S + + > LEFT / v : S => (Left v) : S + +- ``RIGHT 'a``: Pack a value in a union (right case). + +:: + + :: 'b : 'S -> or 'a 'b : 'S + + > RIGHT / v : S => (Right v) : S + +- ``IF_LEFT bt bf``: Inspect a value of a union. + +:: + + :: or 'a 'b : 'A -> 'B + iff bt :: [ 'a : 'A -> 'B] + bf :: [ 'b : 'A -> 'B] + + > IF_LEFT bt bf / (Left a) : S => bt / a : S + > IF_LEFT bt bf / (Right b) : S => bf / b : S + +- ``COMPARE``: Unions comparison + +:: + + :: or 'a 'b : or 'a 'b : 'S -> int : 'S + + > COMPARE / (Left a) : (Left b) : S => COMPARE / a : b : S + > COMPARE / (Left _) : (Right _) : S => -1 : S + > COMPARE / (Right _) : (Left _) : S => 1 : S + > COMPARE / (Right a) : (Right b) : S => COMPARE / a : b : S + +Operations on lists +~~~~~~~~~~~~~~~~~~~ + +- ``CONS``: Prepend an element to a list. + +:: + + :: 'a : list 'a : 'S -> list 'a : 'S + + > CONS / a : { } : S => { a ; } : S + +- ``NIL 'a``: The empty list. + +:: + + :: 'S -> list 'a : 'S + + > NIL / S => {} : S + +- ``IF_CONS bt bf``: Inspect a list. + +:: + + :: list 'a : 'A -> 'B + iff bt :: [ 'a : list 'a : 'A -> 'B] + bf :: [ 'A -> 'B] + + > IF_CONS bt bf / { a ; } : S => bt / a : { } : S + > IF_CONS bt bf / {} : S => bf / S + +- ``MAP body``: Apply the body expression to each element of the list. + The body sequence has access to the stack. + +:: + + :: (list 'elt) : 'A -> (list 'b) : 'A + iff body :: [ 'elt : 'A -> 'b : 'A ] + + > MAP body / {} : S => {} : S + > MAP body / { a ; } : S => { b ; } : S'' + where body / a : S => b : S' + and MAP body / { } : S' => { } : S'' + +- ``SIZE``: Get the number of elements in the list. + +:: + + :: list 'elt : 'S -> nat : 'S + + > SIZE / { _ ; } : S => 1 + s : S + where SIZE / { } : S => s : S + > SIZE / {} : S => 0 : S + + +- ``ITER body``: Apply the body expression to each element of a list. + The body sequence has access to the stack. + +:: + + :: (list 'elt) : 'A -> 'A + iff body :: [ 'elt : 'A -> 'A ] + > ITER body / {} : S => S + > ITER body / { a ; } : S => ITER body / { } : S' + iff body / a : S => S' + + +Domain specific data types +-------------------------- + +- ``timestamp``: Dates in the real world. + +- ``mutez``: A specific type for manipulating tokens. + +- ``address``: An untyped address (implicit account or smart contract). + +- ``contract 'param``: A contract, with the type of its code, + ``contract unit`` for implicit accounts. + +- ``operation``: An internal operation emitted by a contract. + +- ``key``: A public cryptographic key. + +- ``key_hash``: The hash of a public cryptographic key. + +- ``signature``: A cryptographic signature. + +- ``chain_id``: An identifier for a chain, used to distinguish the test and the main chains. + +- ``bls12_381_g1``, ``bls12_381_g2`` : Points on the BLS12-381 curves G\ :sub:`1`\ and G\ :sub:`2`\ , respectively. + +- ``bls12_381_fr`` : An element of the scalar field F\ :sub:`r`\ , used for scalar multiplication on the BLS12-381 curves G\ :sub:`1`\ and G\ :sub:`2`\ . + +- ``sapling_transaction ms``: A :ref:`Sapling` transaction + +- ``sapling_state ms``: A :ref:`Sapling` state + +- ``ticket (t)``: A ticket used to authenticate information of type ``(t)`` on-chain. + +Domain specific operations +-------------------------- + +Operations on timestamps +~~~~~~~~~~~~~~~~~~~~~~~~ + +Timestamps can be obtained by the ``NOW`` operation, or retrieved from +script parameters or globals. + +- ``ADD`` Increment / decrement a timestamp of the given number of + seconds. + +:: + + :: timestamp : int : 'S -> timestamp : 'S + :: int : timestamp : 'S -> timestamp : 'S + + > ADD / seconds : nat (t) : S => (seconds + t) : S + > ADD / nat (t) : seconds : S => (t + seconds) : S + +- ``SUB`` Subtract a number of seconds from a timestamp. + +:: + + :: timestamp : int : 'S -> timestamp : 'S + + > SUB / seconds : nat (t) : S => (seconds - t) : S + +- ``SUB`` Subtract two timestamps. + +:: + + :: timestamp : timestamp : 'S -> int : 'S + + > SUB / seconds(t1) : seconds(t2) : S => (t1 - t2) : S + +- ``COMPARE``: Timestamp comparison. + +:: + + :: timestamp : timestamp : 'S -> int : 'S + + > COMPARE / seconds(t1) : seconds(t2) : S => -1 : S + iff t1 < t2 + > COMPARE / seconds(t1) : seconds(t2) : S => 0 : S + iff t1 = t2 + > COMPARE / seconds(t1) : seconds(t2) : S => 1 : S + iff t1 > t2 + + +Operations on Mutez +~~~~~~~~~~~~~~~~~~~ + +Mutez (micro-Tez) are internally represented by a 64 bit signed +integers. There are restrictions to prevent creating a negative amount +of mutez. Operations are limited to prevent overflow and mixing them +with other numerical types by mistake. They are also mandatory checked +for under/overflows. + +- ``ADD`` + +:: + + :: mutez : mutez : 'S -> mutez : 'S + + > ADD / x : y : S => [FAILED] on overflow + > ADD / x : y : S => (x + y) : S + +- ``SUB`` + +:: + + :: mutez : mutez : 'S -> mutez : 'S + + > SUB / x : y : S => [FAILED] + iff x < y + > SUB / x : y : S => (x - y) : S + +- ``MUL`` + +:: + + :: mutez : nat : 'S -> mutez : 'S + :: nat : mutez : 'S -> mutez : 'S + + > MUL / x : y : S => [FAILED] on overflow + > MUL / x : y : S => (x * y) : S + +- ``EDIV`` + +:: + + :: mutez : nat : 'S -> option (pair mutez mutez) : 'S + :: mutez : mutez : 'S -> option (pair nat mutez) : 'S + + > EDIV / x : 0 : S => None + > EDIV / x : y : S => Some (Pair (x / y) (x % y)) : S + iff y <> 0 + +- ``COMPARE``: Mutez comparison + +:: + + :: mutez : mutez : 'S -> int : 'S + + > COMPARE / x : y : S => -1 : S + iff x < y + > COMPARE / x : y : S => 0 : S + iff x = y + > COMPARE / x : y : S => 1 : S + iff x > y + +Operations on contracts +~~~~~~~~~~~~~~~~~~~~~~~ + +- ``CREATE_CONTRACT { storage 'g ; parameter 'p ; code ... }``: + Forge a new contract from a literal. + +:: + + :: option key_hash : mutez : 'g : 'S + -> operation : address : 'S + +Originate a contract based on a literal. The parameters are the +optional delegate, the initial amount taken from the current +contract, and the initial storage of the originated contract. +The contract is returned as a first class value (to be dropped, passed +as parameter or stored). The ``CONTRACT 'p`` instruction will fail +until it is actually originated. + +- ``TRANSFER_TOKENS``: Forge a transaction. + +:: + + :: 'p : mutez : contract 'p : 'S -> operation : 'S + +The parameter must be consistent with the one expected by the +contract, unit for an account. + +.. _MichelsonSetDelegate_009: + +- ``SET_DELEGATE``: Set or withdraw the contract's delegation. + +:: + + :: option key_hash : 'S -> operation : 'S + +Using this instruction is the only way to modify the delegation of a +smart contract. If the parameter is `None` then the delegation of the +current contract is withdrawn; if it is `Some kh` where `kh` is the +key hash of a registered delegate that is not the current delegate of +the contract, then this operation sets the delegate of the contract to +this registered delegate. The operation fails if `kh` is the current +delegate of the contract or if `kh` is not a registered delegate. + +- ``BALANCE``: Push the current amount of mutez held by the executing + contract, including any mutez added by the calling transaction. + +:: + + :: 'S -> mutez : 'S + +- ``ADDRESS``: Cast the contract to its address. + +:: + + :: contract _ : 'S -> address : 'S + + > ADDRESS / addr : S => addr : S + +- ``CONTRACT 'p``: Cast the address to the given contract type if possible. + +:: + + :: address : 'S -> option (contract 'p) : 'S + + > CONTRACT / addr : S => Some addr : S + iff addr exists and is a contract of parameter type 'p + > CONTRACT / addr : S => Some addr : S + iff 'p = unit and addr is an implicit contract + > CONTRACT / addr : S => None : S + otherwise + +- ``SOURCE``: Push the contract that initiated the current + transaction, i.e. the contract that paid the fees and + storage cost, and whose manager signed the operation + that was sent on the blockchain. Note that since + ``TRANSFER_TOKENS`` instructions can be chained, + ``SOURCE`` and ``SENDER`` are not necessarily the same. + +:: + + :: 'S -> address : 'S + +- ``SENDER``: Push the contract that initiated the current + internal transaction. It may be the ``SOURCE``, but may + also be different if the source sent an order to an intermediate + smart contract, which then called the current contract. + +:: + + :: 'S -> address : 'S + +- ``SELF``: Push the current contract. + +:: + + :: 'S -> contract 'p : 'S + where contract 'p is the type of the current contract + +Note that ``SELF`` is forbidden in lambdas because it cannot be +type-checked; the type of the contract executing the lambda cannot be +known at the point of type-checking the lambda's body. + +- ``SELF_ADDRESS``: Push the address of the current contract. This is + equivalent to ``SELF; ADDRESS`` except that it is allowed in + lambdas. + +:: + + :: 'S -> address : 'S + +Note that ``SELF_ADDRESS`` inside a lambda returns the address of the +contract executing the lambda, which can be different from the address +of the contract in which the ``SELF_ADDRESS`` instruction is written. + +- ``AMOUNT``: Push the amount of the current transaction. + +:: + + :: 'S -> mutez : 'S + +- ``IMPLICIT_ACCOUNT``: Return a default contract with the given + public/private key pair. Any funds deposited in this contract can + immediately be spent by the holder of the private key. This contract + cannot execute Michelson code and will always exist on the + blockchain. + +:: + + :: key_hash : 'S -> contract unit : 'S + +- ``VOTING_POWER``: Return the voting power of a given contract. This voting power + coincides with the weight of the contract in the voting listings (i.e., the rolls + count) which is calculated at the beginning of every voting period. + +:: + + :: key_hash : 'S -> nat : 'S + +Special operations +~~~~~~~~~~~~~~~~~~ + +- ``NOW``: Push the timestamp of the block whose validation triggered + this execution (does not change during the execution of the + contract). + +:: + + :: 'S -> timestamp : 'S + +- ``CHAIN_ID``: Push the chain identifier. + +:: + + :: 'S -> chain_id : 'S + +- ``COMPARE``: Chain identifier comparison + +:: + + :: chain_id : chain_id : 'S -> int : 'S + + > COMPARE / x : y : S => -1 : S + iff x < y + > COMPARE / x : y : S => 0 : S + iff x = y + > COMPARE / x : y : S => 1 : S + iff x > y + +- ``LEVEL``: Push the current block level. + +:: + + :: 'S -> nat : 'S + +- ``TOTAL_VOTING_POWER``: Return the total voting power of all contracts. The total + voting power coincides with the sum of the rolls count of every contract in the voting + listings. The voting listings is calculated at the beginning of every voting period. + +:: + + :: 'S -> nat : 'S + +Operations on bytes +~~~~~~~~~~~~~~~~~~~ + +Bytes are used for serializing data, in order to check signatures and +compute hashes on them. They can also be used to incorporate data from +the wild and untyped outside world. + +- ``PACK``: Serializes a piece of data to its optimized + binary representation. + +:: + + :: 'a : 'S -> bytes : 'S + +- ``UNPACK 'a``: Deserializes a piece of data, if valid. + +:: + + :: bytes : 'S -> option 'a : 'S + +- ``CONCAT``: Byte sequence concatenation. + +:: + + :: bytes : bytes : 'S -> bytes : 'S + + > CONCAT / s : t : S => (s ^ t) : S + + :: bytes list : 'S -> bytes : 'S + + > CONCAT / {} : S => 0x : S + > CONCAT / { s ; } : S => (s ^ r) : S + where CONCAT / { } : S => r : S + +- ``SIZE``: size of a sequence of bytes. + +:: + + :: bytes : 'S -> nat : 'S + +- ``SLICE``: Bytes access. + +:: + + :: nat : nat : bytes : 'S -> option bytes : 'S + + > SLICE / offset : length : s : S => Some ss : S + where ss is the substring of s at the given offset and of the given length + iff offset and (offset + length) are in bounds + > SLICE / offset : length : s : S => None : S + iff offset or (offset + length) are out of bounds + +- ``COMPARE``: Lexicographic comparison. + +:: + + :: bytes : bytes : 'S -> int : 'S + + > COMPARE / s : t : S => -1 : S + iff s < t + > COMPARE / s : t : S => 0 : S + iff s = t + > COMPARE / s : t : S => 1 : S + iff s > t + + +Cryptographic primitives +~~~~~~~~~~~~~~~~~~~~~~~~ + +- ``HASH_KEY``: Compute the b58check of a public key. + +:: + + :: key : 'S -> key_hash : 'S + +- ``BLAKE2B``: Compute a cryptographic hash of the value contents using the + Blake2b-256 cryptographic hash function. + +:: + + :: bytes : 'S -> bytes : 'S + +- ``KECCAK``: Compute a cryptographic hash of the value contents using the + Keccak-256 cryptographic hash function. + +:: + + :: bytes : 'S -> bytes : 'S + +- ``SHA256``: Compute a cryptographic hash of the value contents using the + Sha256 cryptographic hash function. + +:: + + :: bytes : 'S -> bytes : 'S + +- ``SHA512``: Compute a cryptographic hash of the value contents using the + Sha512 cryptographic hash function. + +:: + + :: bytes : 'S -> bytes : 'S + +- ``SHA3``: Compute a cryptographic hash of the value contents using the + SHA3-256 cryptographic hash function. + +:: + + :: bytes : 'S -> bytes : 'S + +- ``CHECK_SIGNATURE``: Check that a sequence of bytes has been signed + with a given key. + +:: + + :: key : signature : bytes : 'S -> bool : 'S + +- ``COMPARE``: Key hash, key and signature comparison + +:: + + :: key_hash : key_hash : 'S -> int : 'S + :: key : key : 'S -> int : 'S + :: signature : signature : 'S -> int : 'S + + > COMPARE / x : y : S => -1 : S + iff x < y + > COMPARE / x : y : S => 0 : S + iff x = y + > COMPARE / x : y : S => 1 : S + iff x > y + +BLS12-381 primitives +~~~~~~~~~~~~~~~~~~~~~~~~ + +- ``NEG``: Negate a curve point or field element. + +:: + + :: bls12_381_g1 : 'S -> bls12_381_g1 : 'S + :: bls12_381_g2 : 'S -> bls12_381_g2 : 'S + :: bls12_381_fr : 'S -> bls12_381_fr : 'S + +- ``ADD``: Add two curve points or field elements. + +:: + + :: bls12_381_g1 : bls12_381_g1 : 'S -> bls12_381_g1 : 'S + :: bls12_381_g2 : bls12_381_g2 : 'S -> bls12_381_g2 : 'S + :: bls12_381_fr : bls12_381_fr : 'S -> bls12_381_fr : 'S + +- ``MUL``: Multiply a curve point or field element by a scalar field element. Fr + elements can be built from naturals by multiplying by the unit of Fr using ``PUSH bls12_381_fr 1; MUL``. Note + that the multiplication will be computed using the natural modulo the order + of Fr. + +:: + + :: bls12_381_g1 : bls12_381_fr : 'S -> bls12_381_g1 : 'S + :: bls12_381_g2 : bls12_381_fr : 'S -> bls12_381_g2 : 'S + :: bls12_381_fr : bls12_381_fr : 'S -> bls12_381_fr : 'S + :: nat : bls12_381_fr : 'S -> bls12_381_fr : 'S + :: int : bls12_381_fr : 'S -> bls12_381_fr : 'S + :: bls12_381_fr : nat : 'S -> bls12_381_fr : 'S + :: bls12_381_fr : int : 'S -> bls12_381_fr : 'S + +- ``INT``: Convert a field element to type ``int``. The returned value is always between ``0`` (inclusive) and the order of Fr (exclusive). + +:: + + :: bls12_381_fr : 'S -> int : 'S + +- ``PAIRING_CHECK``: + Verify that the product of pairings of the given list of points is equal to 1 in Fq12. Returns ``true`` if the list is empty. + Can be used to verify if two pairings P1 and P2 are equal by verifying P1 * P2^(-1) = 1. + +:: + + :: list (pair bls12_381_g1 bls12_381_g2) : 'S -> bool : 'S + + +Sapling operations +~~~~~~~~~~~~~~~~~~ + +Please see the :ref:`Sapling integration` page for a more +comprehensive description of the Sapling protocol. + +- ``SAPLING_VERIFY_UPDATE``: verify and apply a transaction on a Sapling state. + +:: + + :: sapling_transaction ms : sapling_state ms : 'S -> option (pair int (sapling_state ms)): 'S + + > SAPLING_VERIFY_UPDATE / t : s : S => Some (Pair b s') : S + iff the transaction t successfully applied on state s resulting + in balance b and an updated state s' + > SAPLING_VERIFY_UPDATE / t : s : S => None : S + iff the transaction t is invalid with respect to the state + +- ``SAPLING_EMPTY_STATE ms``: Pushes an empty state on the stack. + + :: + + :: 'S -> sapling_state ms: 'S + + > SAPLING_EMPTY_STATE ms / S => sapling_state ms : S + with `sapling_state ms` being the empty state (ie. no one can spend tokens from it) + with memo_size `ms` + + +.. _MichelsonTickets_009: + +Operations on tickets +~~~~~~~~~~~~~~~~~~~~~ + +The following operations deal with tickets. Tickets are a way for smart-contracts +to authenticate data with respect to a Tezos address. This authentication can +then be used to build composable permission systems. + +A contract can create a ticket from a value and an amount. The ticket, when +inspected reveals the value, the amount, and the address of the ticketer (the contract that created the ticket). It is +impossible for a contract to “forge” a ticket that appears to have been created +by another ticketer. + +The amount is a meta-data that can be used to implement UTXOs. + +Tickets cannot be duplicated using the ``DUP`` instruction. + +For example, a ticket could represent a Non Fungible Token (NFT) or a Unspent +Transaction Output (UTXO) which can then be passed around and behave like a value. +This process can happen without the need to interact with a centralized NFT contract, +simplifying the code. + +- ``TICKET``: Create a ticket with the given content and amount. The ticketer is the address + of `SELF`. + +:: + + :: 'a : nat : 'S -> ticket 'a : 'S + +Type ``'a`` must be comparable (the ``COMPARE`` primitive must be defined over it). + +- ``READ_TICKET``: Retrieve the information stored in a ticket. Also return the ticket. + +:: + + :: ticket 'a : 'S -> pair address 'a nat : ticket 'a : 'S + +- ``SPLIT_TICKET``: Delete the given ticket and create two tickets with the + same content and ticketer as the original, but with the new provided amounts. + (This can be used to easily implement UTXOs.) + Return None iff the ticket's original amount is not equal to the sum of the + provided amounts. + +:: + + :: ticket 'a : (pair nat nat) : 'S -> + option (pair (ticket 'a) (ticket 'a)) : 'S + +- ``JOIN_TICKETS``: The inverse of ``SPLIT_TICKET``. Delete the given tickets and create a ticket with an amount equal to the + sum of the amounts of the input tickets. + (This can be used to consolidate UTXOs.) + Return None iff the input tickets have a different ticketer or content. + +:: + + :: (pair (ticket 'a) (ticket 'a)) : 'S -> + option (ticket 'a) : 'S + + +Removed instructions +~~~~~~~~~~~~~~~~~~~~ + +:ref:`005_babylon` deprecated the following instructions. Because no smart +contract used these on Mainnet before they got deprecated, they have been +removed. The Michelson type-checker will reject any contract using them. + +- ``CREATE_CONTRACT { storage 'g ; parameter 'p ; code ... }``: + Forge a new contract from a literal. + +:: + + :: key_hash : option key_hash : bool : bool : mutez : 'g : 'S + -> operation : address : 'S + +See the documentation of the new ``CREATE_CONTRACT`` instruction. The +first, third, and fourth parameters are ignored. + +- ``CREATE_ACCOUNT``: Forge an account creation operation. + +:: + + :: key_hash : option key_hash : bool : mutez : 'S + -> operation : address : 'S + +Takes as argument the manager, optional delegate, the delegatable flag +and finally the initial amount taken from the currently executed +contract. This instruction originates a contract with two entrypoints; +``%default`` of type ``unit`` that does nothing and ``%do`` of type +``lambda unit (list operation)`` that executes and returns the +parameter if the sender is the contract's manager. + +- ``STEPS_TO_QUOTA``: Push the remaining steps before the contract + execution must terminate. + +:: + + :: 'S -> nat : 'S + + +Macros +------ + +In addition to the operations above, several extensions have been added +to the language's concrete syntax. If you are interacting with the node +via RPC, bypassing the client, which expands away these macros, you will +need to desugar them yourself. + +These macros are designed to be unambiguous and reversible, meaning that +errors are reported in terms of desugared syntax. Below you'll see +these macros defined in terms of other syntactic forms. That is how +these macros are seen by the node. + +Compare +~~~~~~~ + +Syntactic sugar exists for merging ``COMPARE`` and comparison +combinators, and also for branching. + +- ``CMP{EQ|NEQ|LT|GT|LE|GE}`` + +:: + + > CMP(\op) / S => COMPARE ; (\op) / S + +- ``IF{EQ|NEQ|LT|GT|LE|GE} bt bf`` + +:: + + > IF(\op) bt bf / S => (\op) ; IF bt bf / S + +- ``IFCMP{EQ|NEQ|LT|GT|LE|GE} bt bf`` + +:: + + > IFCMP(\op) / S => COMPARE ; (\op) ; IF bt bf / S + +Fail +~~~~ + +The ``FAIL`` macros is equivalent to ``UNIT; FAILWITH`` and is callable +in any context since it does not use its input stack. + +- ``FAIL`` + +:: + + > FAIL / S => UNIT; FAILWITH / S + +Assertion macros +~~~~~~~~~~~~~~~~ + +All assertion operations are syntactic sugar for conditionals with a +``FAIL`` instruction in the appropriate branch. When possible, use them +to increase clarity about illegal states. + +- ``ASSERT`` + +:: + + > ASSERT => IF {} {FAIL} + +- ``ASSERT_{EQ|NEQ|LT|LE|GT|GE}`` + +:: + + > ASSERT_(\op) => IF(\op) {} {FAIL} + +- ``ASSERT_CMP{EQ|NEQ|LT|LE|GT|GE}`` + +:: + + > ASSERT_CMP(\op) => IFCMP(\op) {} {FAIL} + +- ``ASSERT_NONE`` + +:: + + > ASSERT_NONE => IF_NONE {} {FAIL} + +- ``ASSERT_SOME`` + +:: + + > ASSERT_SOME @x => IF_NONE {FAIL} {RENAME @x} + +- ``ASSERT_LEFT`` + +:: + + > ASSERT_LEFT @x => IF_LEFT {RENAME @x} {FAIL} + +- ``ASSERT_RIGHT`` + +:: + + > ASSERT_RIGHT @x => IF_LEFT {FAIL} {RENAME @x} + +Syntactic Conveniences +~~~~~~~~~~~~~~~~~~~~~~ + +These macros are simply more convenient syntax for various common +operations. + +- ``P(\left=A|P(\left)(\right))(\right=I|P(\left)(\right))R``: A syntactic sugar + for building nested pairs. In the case of right combs, `PAIR n` is more efficient. + +:: + + > PA(\right)R / S => DIP ((\right)R) ; PAIR / S + > P(\left)IR / S => (\left)R ; PAIR / S + > P(\left)(\right)R => (\left)R ; DIP ((\right)R) ; PAIR / S + +A good way to quickly figure which macro to use is to mentally parse the +macro as ``P`` for pair constructor, ``A`` for left leaf and ``I`` for +right leaf. The macro takes as many elements on the stack as there are +leaves and constructs a nested pair with the shape given by its name. + +Take the macro ``PAPPAIIR`` for instance: + +:: + + P A P P A I I R + ( l, ( ( l, r ), r )) + +A typing rule can be inferred: + +:: + + PAPPAIIR + :: 'a : 'b : 'c : 'd : 'S -> (pair 'a (pair (pair 'b 'c) 'd)) + +- ``UNP(\left=A|P(\left)(\right))(\right=I|P(\left)(\right))R``: A syntactic sugar + for destructing nested pairs. These macros follow the same convention + as the previous one. + +:: + + > UNPA(\right)R / S => UNPAIR ; DIP (UN(\right)R) / S + > UNP(\left)IR / S => UNPAIR ; UN(\left)R / S + > UNP(\left)(\right)R => UNPAIR ; DIP (UN(\right)R) ; UN(\left)R / S + +- ``C[AD]+R``: A syntactic sugar for accessing fields in nested pairs. In the case of right combs, ``CAR k`` and ``CDR k`` are more efficient. + +:: + + > CA(\rest=[AD]+)R / S => CAR ; C(\rest)R / S + > CD(\rest=[AD]+)R / S => CDR ; C(\rest)R / S + +- ``CAR k``: Access the ``k`` -th part of a right comb of size ``n > k + 1``. ``CAR 0`` is equivalent to ``CAR`` and in general ``CAR k`` is equivalent to ``k`` times the ``CDR`` instruction followed by once the ``CAR`` instruction. Note that this instruction cannot access the last element of a right comb; ``CDR k`` should be used for that. + +:: + + > CAR n / S => GET (2n+1) / S + +- ``CDR k``: Access the rightmost element of a right comb of size ``k``. ``CDR 0`` is a no-op, ``CDR 1`` is equivalent to ``CDR`` and in general ``CDR k`` is equivalent to ``k`` times the ``CDR`` instruction. Note that on a right comb of size ``n > k >= 2``, ``CDR k`` will return the right comb composed of the same elements but the ``k`` leftmost ones. + +:: + + > CDR n / S => GET (2n) / S + +- ``IF_SOME bt bf``: Inspect an optional value. + +:: + + > IF_SOME bt bf / S => IF_NONE bf bt / S + +- ``IF_RIGHT bt bf``: Inspect a value of a union. + +:: + + > IF_RIGHT bt bf / S => IF_LEFT bf bt / S + +- ``SET_CAR``: Set the left field of a pair. This is equivalent to ``SWAP; UPDATE 1``. + +:: + + > SET_CAR => CDR ; SWAP ; PAIR + +- ``SET_CDR``: Set the right field of a pair. This is equivalent to ``SWAP; UPDATE 2``. + +:: + + > SET_CDR => CAR ; PAIR + +- ``SET_C[AD]+R``: A syntactic sugar for setting fields in nested + pairs. In the case of right combs, `UPDATE n` is more efficient. + +:: + + > SET_CA(\rest=[AD]+)R / S => + { DUP ; DIP { CAR ; SET_C(\rest)R } ; CDR ; SWAP ; PAIR } / S + > SET_CD(\rest=[AD]+)R / S => + { DUP ; DIP { CDR ; SET_C(\rest)R } ; CAR ; PAIR } / S + +- ``MAP_CAR`` code: Transform the left field of a pair. + +:: + + > MAP_CAR code => DUP ; CDR ; DIP { CAR ; code } ; SWAP ; PAIR + +- ``MAP_CDR`` code: Transform the right field of a pair. + +:: + + > MAP_CDR code => DUP ; CDR ; code ; SWAP ; CAR ; PAIR + +- ``MAP_C[AD]+R`` code: A syntactic sugar for transforming fields in + nested pairs. + +:: + + > MAP_CA(\rest=[AD]+)R code / S => + { DUP ; DIP { CAR ; MAP_C(\rest)R code } ; CDR ; SWAP ; PAIR } / S + > MAP_CD(\rest=[AD]+)R code / S => + { DUP ; DIP { CDR ; MAP_C(\rest)R code } ; CAR ; PAIR } / S + +Concrete syntax +--------------- +.. _ConcreteSyntax_009: + +The concrete language is very close to the formal notation of the +specification. Its structure is extremely simple: an expression in the +language can only be one of the five following constructs. + +1. An integer in decimal notation. +2. A character string. +3. A byte sequence in hexadecimal notation prefixed by ``0x``. +4. The application of a primitive to a sequence of expressions. +5. A sequence of expressions. + +This simple five cases notation is called :ref:`Micheline`. + +Constants +~~~~~~~~~ + +There are three kinds of constants: + +1. Integers or naturals in decimal notation. +2. Strings, with some usual escape sequences: ``\n``, ``\\``, + ``\"``. Unescaped line-breaks (both ``\n`` and ``\r``) cannot + appear in a Michelson string. Moreover, the current version of + Michelson restricts strings to be the printable subset of 7-bit + ASCII, namely characters with codes from within `[32, 126]` range, + plus the escaped characters mentioned above. +3. Byte sequences in hexadecimal notation, prefixed with ``0x``. + +Differences with the formal notation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The concrete syntax follows the same lexical conventions as the +specification: instructions are represented by uppercase identifiers, +type constructors by lowercase identifiers, and constant constructors +are capitalized. + +All domain specific constants are Micheline constants with specific +formats. Some have two variants accepted by the data type checker: a +readable one in a string and an optimized. + +- ``mutez`` amounts are written as naturals. +- ``timestamp``\ s are written either using ``RFC3339`` notation + in a string (readable), or as the number of seconds since Epoch + in a natural (optimized). +- ``contract``\ s, ``address``\ es, ``key``\ s and ``signature``\ s + are written as strings, in their usual Base58 encoded versions + (readable), or as their raw bytes (optimized). +- ``bls12_381_g1``\ s and ``bls12_381_g2``\ s are written as their raw bytes, using a big-endian point encoding, `as specified here `__. +- ``bls12_381_fr``\ s are written as their raw bytes, using a little-endian encoding. + +The optimized versions should not reach the RPCs, the protocol code +will convert to optimized by itself when forging operations, storing +to the database, and before hashing to get a canonical representation +of a datum for a given type. + +To prevent errors, control flow primitives that take instructions as +parameters require sequences in the concrete syntax. + +:: + + IF { instr1_true ; instr2_true ; ... } + { instr1_false ; instr2_false ; ... } + +Main program structure +~~~~~~~~~~~~~~~~~~~~~~ + +The toplevel of a smart contract file must be an un-delimited sequence +of three primitive applications (in no particular order) that provide its +``code``, ``parameter`` and ``storage`` fields. + +See the next section for a concrete example. + +Annotations +----------- + +The annotation mechanism of Michelson provides ways to better track +data on the stack and to give additional type constraints. Except for +a single exception specified just after, annotations are only here to +add constraints, *i.e.* they cannot turn an otherwise rejected program +into an accepted one. The notable exception to this rule is for +entrypoints: the semantics of the `CONTRACT` and `SELF` instructions vary depending on +their constructor annotations, and some contract origination may fail due +to invalid entrypoint constructor annotations. + +Stack visualization tools like the Michelson's Emacs mode print +annotations associated with each type in the program, as propagated by +the typechecker as well as variable annotations on the types of elements +in the stack. This is useful as a debugging aid. + +We distinguish three kinds of annotations: + +- type annotations, written ``:type_annot``, +- variable annotations, written ``@var_annot``, +- and field or constructors annotations, written ``%field_annot``. + +Type annotations +~~~~~~~~~~~~~~~~ + +Each type can be annotated with at most one type annotation. They are +used to give names to types. For types to be equal, their unnamed +version must be equal and their names must be the same or at least one +type must be unnamed. + +For instance, the following Michelson program which put its integer +parameter in the storage is not well typed: + +.. code-block:: michelson + + parameter (int :p) ; + storage (int :s) ; + code { UNPAIR ; SWAP ; DROP ; NIL operation ; PAIR } + +Whereas this one is: + +.. code-block:: michelson + + parameter (int :p) ; + storage int ; + code { UNPAIR ; SWAP ; DROP ; NIL operation ; PAIR } + +Inner components of composed typed can also be named. + +:: + + (pair :point (int :x_pos) (int :y_pos)) + +Push-like instructions, that act as constructors, can also be given a +type annotation. The stack type will then have on top a type with a corresponding name. + +:: + + UNIT :t + :: 'A -> (unit :t) : 'A + + PAIR :t + :: 'a : 'b : 'S -> (pair :t 'a 'b) : 'S + + SOME :t + :: 'a : 'S -> (option :t 'a) : 'S + + NONE :t 'a + :: 'S -> (option :t 'a) : 'S + + LEFT :t 'b + :: 'a : 'S -> (or :t 'a 'b) : 'S + + RIGHT :t 'a + :: 'b : 'S -> (or :t 'a 'b) : 'S + + NIL :t 'a + :: 'S -> (list :t 'a) : 'S + + EMPTY_SET :t 'elt + :: 'S -> (set :t 'elt) : 'S + + EMPTY_MAP :t 'key 'val + :: 'S -> (map :t 'key 'val) : 'S + + EMPTY_BIG_MAP :t 'key 'val + :: 'S -> (big_map :t 'key 'val) : 'S + + +A no-op instruction ``CAST`` ensures the top of the stack has the +specified type, and change its type if it is compatible. In particular, +this allows to change or remove type names explicitly. + +:: + + CAST 'b + :: 'a : 'S -> 'b : 'S + iff 'a = 'b + + > CAST t / a : S => a : S + + +Variable annotations +~~~~~~~~~~~~~~~~~~~~ + +Variable annotations can only be used on instructions that produce +elements on the stack. An instruction that produces ``n`` elements on +the stack can be given at most ``n`` variable annotations. + +The stack type contains both the types of each element in the stack, as +well as an optional variable annotation for each element. In this +sub-section we note: + +- ``[]`` for the empty stack, +- ``@annot (top) : (rest)`` for the stack whose first value has type ``(top)`` and is annotated with variable annotation ``@annot`` and whose queue has stack type ``(rest)``. + +The instructions which do not accept any variable annotations are: + +:: + + DROP + SWAP + DIG + DUG + IF_NONE + IF_LEFT + IF_CONS + ITER + IF + LOOP + LOOP_LEFT + DIP + FAILWITH + +The instructions which accept at most one variable annotation are: + +:: + + DUP + PUSH + UNIT + SOME + NONE + PAIR + CAR + CDR + LEFT + RIGHT + NIL + CONS + SIZE + MAP + MEM + EMPTY_SET + EMPTY_MAP + EMPTY_BIG_MAP + UPDATE + GET + LAMBDA + EXEC + ADD + SUB + CONCAT + MUL + OR + AND + XOR + NOT + ABS + ISNAT + INT + NEG + EDIV + LSL + LSR + COMPARE + EQ + NEQ + LT + GT + LE + GE + ADDRESS + CONTRACT + SET_DELEGATE + IMPLICIT_ACCOUNT + NOW + LEVEL + AMOUNT + BALANCE + HASH_KEY + CHECK_SIGNATURE + BLAKE2B + SOURCE + SENDER + SELF + SELF_ADDRESS + CAST + RENAME + CHAIN_ID + +The instructions which accept at most two variable annotations are: + +:: + + UNPAIR + CREATE_CONTRACT + +Annotations on instructions that produce multiple elements on the stack +will be used in order, where the first variable annotation is given to +the top-most element on the resulting stack. Instructions that produce +``n`` elements on the stack but are given less than ``n`` variable +annotations will see only their top-most stack type elements annotated. + +:: + + UNPAIR @fist @second + :: pair 'a 'b : 'S + -> @first 'a : @second 'b : 'S + + UNPAIR @first + :: pair 'a 'b : 'S + -> @first 'a : 'b : 'S + +A no-op instruction ``RENAME`` allows to rename variables in the stack +or to erase variable annotations in the stack. + +:: + + RENAME @new + :: @old 'a ; 'S -> @new 'a : 'S + + RENAME + :: @old 'a ; 'S -> 'a : 'S + + +Field and constructor annotations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Components of pair types, option types and or types can be annotated +with a field or constructor annotation. This feature is useful to encode +records fields and constructors of sum types. + +:: + + (pair :point + (int %x) + (int %y)) + +The previous Michelson type can be used as visual aid to represent the +record type (given in OCaml-like syntax): + +:: + + type point = { x : int ; y : int } + +Similarly, + +:: + + (or :t + (int %A) + (or + (bool %B) + (pair %C + (nat %n1) + (nat %n2)))) + +can be used to represent the algebraic data type (in OCaml-like syntax): + +:: + + type t = + | A of int + | B of bool + | C of { n1 : nat ; n2 : nat } + + +Field annotations are part of the type (at the same level as type name +annotations), and so types with differing field names (if present) are +not considered equal. + +Instructions that construct elements of composed types can also be +annotated with one or multiple field annotations (in addition to type +and variable annotations). + +:: + + PAIR %fst %snd + :: 'a : 'b : 'S -> (pair ('a %fst) ('b %snd)) : 'S + + LEFT %left %right 'b + :: 'a : 'S -> (or ('a %left) ('b %right)) : 'S + + RIGHT %left %right 'a + :: 'b : 'S -> (or ('a %left) ('b %right)) : 'S + +To improve readability and robustness, instructions ``CAR`` and ``CDR`` +accept one field annotation. For the contract to type check, the name of +the accessed field in the destructed pair must match the one given here. + +:: + + CAR %fst + :: (pair ('a %fst) 'b) : S -> 'a : 'S + + CDR %snd + :: (pair 'a ('b %snd)) : S -> 'b : 'S + + +Syntax +~~~~~~ + +Primitive applications can receive one or many annotations. + +An annotation is a sequence of characters that matches the regular +expression ``@%|@%%|%@|[@:%][_0-9a-zA-Z][_0-9a-zA-Z\.%@]*``. +Note however that ``@%``, ``@%%`` and ``%@`` are +:ref:`special annotations ` and are not allowed everywhere. + +Annotations come after the primitive name and before its potential arguments. + +:: + + (prim @v :t %x arg1 arg2 ...) + + +Ordering between different kinds of annotations is not significant, but +ordering among annotations of the same kind is. Annotations of the same +kind must be grouped together. + +For instance these two annotated instructions are equivalent: + +:: + + PAIR :t @my_pair %x %y + + PAIR %x %y :t @my_pair + +An annotation can be empty, in this case it will mean *no annotation* +and can be used as a wildcard. For instance, it is useful to annotate +only the right field of a pair instruction ``PAIR % %right`` or to +ignore field access constraints, *e.g.* in the macro ``UNPPAIPAIR %x1 % +%x3 %x4``. + +Annotations and macros +~~~~~~~~~~~~~~~~~~~~~~ + +Macros also support annotations, which are propagated on their expanded +forms. As with instructions, macros that produce ``n`` values on the +stack accept ``n`` variable annotations. + +:: + + DUU+P @annot + > DUU(\rest=U*)P @annot / S => DIP (DU(\rest)P @annot) ; SWAP / S + + C[AD]+R @annot %field_name + > CA(\rest=[AD]+)R @annot %field_name / S => CAR ; C(\rest)R @annot %field_name / S + > CD(\rest=[AD]+)R @annot %field_name / S => CDR ; C(\rest)R @annot %field_name / S + + ``CMP{EQ|NEQ|LT|GT|LE|GE}`` @annot + > CMP(\op) @annot / S => COMPARE ; (\op) @annot / S + +The variable annotation on ``SET_C[AD]+R`` and ``MAP_C[AD]+R`` annotates +the resulting toplevel pair while its field annotation is used to check +that the modified field is the expected one. + +:: + + SET_C[AD]+R @var %field + > SET_CAR @var %field => CDR %field ; SWAP ; PAIR @var + > SET_CDR @var %field => CAR %field ; PAIR @var + > SET_CA(\rest=[AD]+)R @var %field / S => + { DUP ; DIP { CAR ; SET_C(\rest)R %field } ; CDR ; SWAP ; PAIR @var } / S + > SET_CD(\rest=[AD]+)R @var %field/ S => + { DUP ; DIP { CDR ; SET_C(\rest)R %field } ; CAR ; PAIR @var } / S + + MAP_C[AD]+R @var %field code + > MAP_CAR code => DUP ; CDR ; DIP { CAR %field ; code } ; SWAP ; PAIR @var + > MAP_CDR code => DUP ; CDR %field ; code ; SWAP ; CAR ; PAIR @var + > MAP_CA(\rest=[AD]+)R @var %field code / S => + { DUP ; DIP { CAR ; MAP_C(\rest)R %field code } ; CDR ; SWAP ; PAIR @var} / S + > MAP_CD(\rest=[AD]+)R @var %field code / S => + { DUP ; DIP { CDR ; MAP_C(\rest)R %field code } ; CAR ; PAIR @var} / S + +Macros for nested ``PAIR`` accept multiple annotations. Field +annotations for ``PAIR`` give names to leaves of the constructed +nested pair, in order. This next snippet gives examples instead of +generic rewrite rules for readability purposes. + +:: + + PAPPAIIR @p %x1 %x2 %x3 %x4 + :: 'a : 'b : 'c : 'd : 'S + -> @p (pair ('a %x1) (pair (pair ('b %x) ('c %x3)) ('d %x4))) : 'S + + PAPAIR @p %x1 %x2 %x3 + :: 'a : 'b : 'c : 'S -> @p (pair ('a %x1) (pair ('b %x) ('c %x3))) : 'S + +Annotations for nested ``UNPAIR`` are deprecated. + +Automatic variable and field annotations inferring +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When no annotation is provided by the Michelson programmer, the +typechecker infers some annotations in specific cases. This greatly +helps users track information in the stack for bare contracts. + +For unannotated accesses with ``CAR`` and ``CDR`` to fields that are +named will be appended (with an additional ``.`` character) to the pair +variable annotation. + +:: + + CDAR + :: @p (pair ('a %foo) (pair %bar ('b %x) ('c %y))) : 'S -> @p.bar.x 'b : 'S + +If fields are not named but the pair is still named in the stack then +``.car`` or ``.cdr`` will be appended. + +:: + + CDAR + :: @p (pair 'a (pair 'b 'c)) : 'S -> @p.cdr.car 'b : 'S + +If the original pair is not named in the stack, but a field annotation +is present in the pair type the accessed value will be annotated with a +variable annotation corresponding to the field annotation alone. + +:: + + CDAR + :: (pair ('a %foo) (pair %bar ('b %x) ('c %y))) : 'S -> @bar.x 'b : 'S + +A similar mechanism is used for context dependent instructions: + +:: + + ADDRESS :: @c contract _ : 'S -> @c.address address : 'S + + CONTRACT 'p :: @a address : 'S -> @a.contract contract 'p : 'S + + BALANCE :: 'S -> @balance mutez : 'S + + SOURCE :: 'S -> @source address : 'S + + SENDER :: 'S -> @sender address : 'S + + SELF :: 'S -> @self contract 'p : 'S + + SELF_ADDRESS :: 'S -> @self address : 'S + + AMOUNT :: 'S -> @amount mutez : 'S + + NOW :: 'S -> @now timestamp : 'S + + LEVEL :: 'S -> @level nat : 'S + +Inside nested code blocks, bound items on the stack will be given a +default variable name annotation depending on the instruction and stack +type (which can be changed). For instance the annotated typing rule for +``ITER`` on lists is: + +:: + + ITER body + :: @l (list 'e) : 'A -> 'A + iff body :: [ @l.elt e' : 'A -> 'A ] + +Special annotations +~~~~~~~~~~~~~~~~~~~ +.. _SpecialAnnotations_009: + +The special variable annotations ``@%`` and ``@%%`` can be used on instructions +``CAR``, ``CDR``, and ``UNPAIR``. It means to use the accessed field name (if any) as +a name for the value on the stack. The following typing rule +demonstrates their use for instruction ``CAR``. + +:: + + CAR @% + :: @p (pair ('a %fst) ('b %snd)) : 'S -> @fst 'a : 'S + + CAR @%% + :: @p (pair ('a %fst) ('b %snd)) : 'S -> @p.fst 'a : 'S + +The special field annotation ``%@`` can be used on instructions +``PAIR``, ``LEFT`` and ``RIGHT``. It means to use the variable +name annotation in the stack as a field name for the constructed +element. Two examples with ``PAIR`` follows, notice the special +treatment of annotations with ``.``. + +:: + + PAIR %@ %@ + :: @x 'a : @y 'b : 'S -> (pair ('a %x) ('b %y)) : 'S + + PAIR %@ %@ + :: @p.x 'a : @p.y 'b : 'S -> @p (pair ('a %x) ('b %y)) : 'S + :: @p.x 'a : @q.y 'b : 'S -> (pair ('a %x) ('b %y)) : 'S + +Entrypoints +----------- + +The specification up to this point has been mostly ignoring existence +of entrypoints: a mechanism of contract level polymorphism. This +mechanism is optional, non intrusive, and transparent to smart +contracts that don't use them. This section is to be read as a patch +over the rest of the specification, introducing rules that apply only +in presence of contracts that make use of entrypoints. + +Defining and calling entrypoints +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Entrypoints piggyback on the constructor annotations. A contract with +entrypoints is basically a contract that takes a disjunctive type (a +nesting of ``or`` types) as the root of its input parameter, decorated +with constructor annotations. An extra check is performed on these +constructor annotations: a contract cannot define two entrypoints with +the same name. + +An external transaction can include an entrypoint name alongside the +parameter value. In that case, if there is a constructor annotation +with this name at any position in the nesting of ``or`` types, the +value is automatically wrapped into the according constructors. If the +transaction specifies an entrypoint, but there is no such constructor +annotation, the transaction fails. + +For instance, suppose the following input type. + +``parameter (or (or (nat %A) (bool %B)) (or %maybe_C (unit %Z) (string %C)))`` + +The input values will be wrapped as in the following examples. + +:: + + +------------+-----------+---------------------------------+ + | entrypoint | input | wrapped input | + +------------+-----------+---------------------------------+ + | %A | 3 | Left (Left 3) | + | %B | False | Left (Right False) | + | %C | "bob" | Right (Right "bob") | + | %Z | Unit | Right (Left Unit) | + | %maybe_C | Right "x" | Right (Right "x") | + | %maybe_C | Left Unit | Right (Left Unit) | + +------------+-----------+---------------------------------+ + | not given | value | value (untouched) | + | %BAD | _ | failure, contract not called | + +------------+-----------+---------------------------------+ + +The ``default`` entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A special semantics is assigned to the ``default`` entrypoint. If the +contract does not explicitly declare a ``default`` entrypoint, then it +is automatically assigned to the root of the parameter +type. Conversely, if the contract is called without specifying an +entrypoint, then it is assumed to be called with the ``default`` +entrypoint. This behaviour makes the entrypoint system completely +transparent to contracts that do not use it. + +This is the case for the previous example, for instance. If a value is +passed to such a contract specifying entrypoint ``default``, then the +value is fed to the contract untouched, exactly as if no entrypoint +was given. + +A non enforced convention is to make the entrypoint ``default`` of +type unit, and to implement the crediting operation (just receive the +transferred tokens). + +A consequence of this semantics is that if the contract uses the +entrypoint system and defines a ``default`` entrypoint somewhere else +than at the root of the parameter type, then it must provide an +entrypoint for all the paths in the toplevel disjunction. Otherwise, +some parts of the contracts would be dead code. + +Another consequence of setting the entrypoint somewhere else than at +the root is that it makes it impossible to send the raw values of the +full parameter type to a contract. A trivial solution for that is to +name the root of the type. The conventional name for that is ``root``. + +Let us recapitulate this by tweaking the names of the previous example. + +``parameter %root (or (or (nat %A) (bool %B)) (or (unit %default) string))`` + +The input values will be wrapped as in the following examples. + +:: + + +------------+---------------------+-----------------------+ + | entrypoint | input | wrapped input | + +------------+---------------------+-----------------------+ + | %A | 3 | Left (Left 3) | + | %B | False | Left (Right False) | + | %default | Unit | Right (Left Unit) | + | %root | Right (Right "bob") | Right (Right "bob") | + +------------+---------------------+-----------------------+ + | not given | Unit | Right (Left Unit) | + | %BAD | _ | failure, contract not | + +------------+---------------------+-----------------------+ + +Calling entrypoints from Michelson +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Michelson code can also produce transactions to a specific entrypoint. + +For this, both types ``address`` and ``contract`` have the ability to +denote not just an address, but a pair of an address and an +entrypoint. The concrete notation is ``"address%entrypoint"``. +Note that ``"address"`` is strictly equivalent to ``"address%default"``, +and for clarity, the second variant is forbidden in the concrete syntax. + +When the ``TRANSFER_TOKENS`` instruction is called, it places the +entrypoint provided in the contract handle in the transaction. + +The ``CONTRACT t`` instruction has a variant ``CONTRACT %entrypoint +t``, that works as follows. Note that ``CONTRACT t`` is strictly +equivalent to ``CONTRACT %default t``, and for clarity, the second +variant is forbidden in the concrete syntax. + +:: + + +---------------+---------------------+------------------------------------------+ + | input address | instruction | output contract | + +---------------+---------------------+------------------------------------------+ + | "addr" | CONTRACT t | (Some "addr") if contract exists, has a | + | | | default entrypoint of type t, or has no | + | | | default entrypoint and parameter type t | + +---------------+---------------------+------------------------------------------+ + | "addr%name" | CONTRACT t | (Some "addr%name") if addr exists and | + +---------------+---------------------+ has an entrypoint %name of type t | + | "addr" | CONTRACT %name t | | + +---------------+---------------------+------------------------------------------+ + | "addr%_" | CONTRACT %_ t | None | + +---------------+---------------------+------------------------------------------+ + +Similarly, the ``SELF`` instruction has a variant ``SELF %entrypoint``, +that is only well-typed if the current contract has an entrypoint named ``%entrypoint``. + +- ``SELF %entrypoint`` + +:: + + :: 'S -> contract 'p : 'S + where contract 'p is the type of the entrypoint %entrypoint of the current contract + +Implicit accounts are considered to have a single ``default`` +entrypoint of type ``Unit``. + +JSON syntax +----------- + +Micheline expressions are encoded in JSON like this: + +- An integer ``N`` is an object with a single field ``"int"`` whose + value is the decimal representation as a string. + + ``{ "int": "N" }`` + +- A string ``"contents"`` is an object with a single field ``"string"`` + whose value is the decimal representation as a string. + + ``{ "string": "contents" }`` + +- A sequence is a JSON array. + + ``[ expr, ... ]`` + +- A primitive application is an object with two fields ``"prim"`` for + the primitive name and ``"args"`` for the arguments (that must + contain an array). A third optional field ``"annots"`` contains a + list of annotations, including their leading ``@``, ``%`` or ``:`` + sign. + + ``{ "prim": "pair", "args": [ { "prim": "nat", "args": [] }, { "prim": "nat", "args": [] } ], "annots": [":t"] }`` + +As in the concrete syntax, all domain specific constants are encoded as +strings. + +Examples +--------- + +Contracts in the system are stored as a piece of code and a global data +storage. The type of the global data of the storage is fixed for each +contract at origination time. This is ensured statically by checking on +origination that the code preserves the type of the global data. For +this, the code of the contract is checked to be of type +``lambda (pair 'arg 'global) -> (pair (list operation) 'global)`` where +``'global`` is the type of the original global store given on origination. +The contract also takes a parameter and returns a list of internal operations, +hence the complete calling convention above. The internal operations are +queued for execution when the contract returns. + +Empty contract +~~~~~~~~~~~~~~ + +The simplest contract is the contract for which the ``parameter`` and +``storage`` are all of type ``unit``. This contract is as follows: + +.. code-block:: michelson + + code { CDR ; # keep the storage + NIL operation ; # return no internal operation + PAIR }; # respect the calling convention + storage unit; + parameter unit; + + +Example contract with entrypoints +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following contract maintains a number in its storage. It has two +entrypoints ``add`` and ``sub`` to modify it, and the default +entrypoint, of type ``unit`` will reset it to ``0``. + +:: + + { parameter (or (or (nat %add) (nat %sub)) (unit %default)) ; + storage int ; + code { AMOUNT ; PUSH mutez 0 ; ASSERT_CMPEQ ; UNPAIR ; + IF_LEFT + { IF_LEFT { ADD } { SWAP ; SUB } } + { DROP ; DROP ; PUSH int 0 } ; + NIL operation ; PAIR } } + +Multisig contract +~~~~~~~~~~~~~~~~~ + +The multisig is a typical access control contract. The ownership of +the multisig contract is shared between ``N`` participants represented +by their public keys in the contract's storage. Any action on the +multisig contract needs to be signed by ``K`` participants where the +threshold ``K`` is also stored in the storage. + +To avoid replay of the signatures sent to the contract, the signed +data include not only a description of the action to perform but also +the address of the multisig contract and a counter that gets +incremented at each successful call to the contract. + +The multisig commands of :ref:`Tezos command line client ` +use this +smart contract. Moreover, `functional correctness of this contract has +been verified +`__ +using the Coq proof assistant. + + +.. code-block:: michelson + + parameter (pair + (pair :payload + (nat %counter) # counter, used to prevent replay attacks + (or :action # payload to sign, represents the requested action + (pair :transfer # transfer tokens + (mutez %amount) # amount to transfer + (contract %dest unit)) # destination to transfer to + (or + (option %delegate key_hash) # change the delegate to this address + (pair %change_keys # change the keys controlling the multisig + (nat %threshold) # new threshold + (list %keys key))))) # new list of keys + (list %sigs (option signature))); # signatures + + storage (pair (nat %stored_counter) (pair (nat %threshold) (list %keys key))) ; + + code + { + UNPAIR ; SWAP ; DUP ; DIP { SWAP } ; + DIP + { + UNPAIR ; + # pair the payload with the current contract address, to ensure signatures + # can't be replayed across different contracts if a key is reused. + DUP ; SELF ; ADDRESS ; CHAIN_ID ; PAIR ; PAIR ; + PACK ; # form the binary payload that we expect to be signed + DIP { UNPAIR @counter ; DIP { SWAP } } ; SWAP + } ; + + # Check that the counters match + UNPAIR @stored_counter; DIP { SWAP }; + ASSERT_CMPEQ ; + + # Compute the number of valid signatures + DIP { SWAP } ; UNPAIR @threshold @keys; + DIP + { + # Running count of valid signatures + PUSH @valid nat 0; SWAP ; + ITER + { + DIP { SWAP } ; SWAP ; + IF_CONS + { + IF_SOME + { SWAP ; + DIP + { + SWAP ; DIIP { DIP { DUP } ; SWAP } ; + # Checks signatures, fails if invalid + CHECK_SIGNATURE ; ASSERT ; + PUSH nat 1 ; ADD @valid } } + { SWAP ; DROP } + } + { + # There were fewer signatures in the list + # than keys. Not all signatures must be present, but + # they should be marked as absent using the option type. + FAIL + } ; + SWAP + } + } ; + # Assert that the threshold is less than or equal to the + # number of valid signatures. + ASSERT_CMPLE ; + DROP ; DROP ; + + # Increment counter and place in storage + DIP { UNPAIR ; PUSH nat 1 ; ADD @new_counter ; PAIR} ; + + # We have now handled the signature verification part, + # produce the operation requested by the signers. + NIL operation ; SWAP ; + IF_LEFT + { # Transfer tokens + UNPAIR ; UNIT ; TRANSFER_TOKENS ; CONS } + { IF_LEFT { + # Change delegate + SET_DELEGATE ; CONS } + { + # Change set of signatures + DIP { SWAP ; CAR } ; SWAP ; PAIR ; SWAP }} ; + PAIR } + + + +Full grammar +------------ + +:: + + ::= + | + | + | + | Unit + | True + | False + | Pair ... + | Left + | Right + | Some + | None + | { ; ... } + | { Elt ; ... } + | instruction + ::= + | [0-9]+ + ::= + | + | - + ::= + | "*" + ::= + | \" + | \r + | \n + | \t + | \b + | \\ + | [^"\] + ::= + | 0x[0-9a-fA-F]+ + ::= + | { ... } + | DROP + | DROP + | DUP + | DUP + | SWAP + | DIG + | DUG + | PUSH + | SOME + | NONE + | UNIT + | NEVER + | IF_NONE { ... } { ... } + | PAIR + | PAIR + | CAR + | CDR + | UNPAIR + | UNPAIR + | LEFT + | RIGHT + | IF_LEFT { ... } { ... } + | NIL + | CONS + | IF_CONS { ... } { ... } + | SIZE + | EMPTY_SET + | EMPTY_MAP + | EMPTY_BIG_MAP + | MAP { ... } + | ITER { ... } + | MEM + | GET + | GET + | UPDATE + | UPDATE + | IF { ... } { ... } + | LOOP { ... } + | LOOP_LEFT { ... } + | LAMBDA { ... } + | EXEC + | APPLY + | DIP { ... } + | DIP { ... } + | FAILWITH + | CAST + | RENAME + | CONCAT + | SLICE + | PACK + | UNPACK + | ADD + | SUB + | MUL + | EDIV + | ABS + | ISNAT + | INT + | NEG + | LSL + | LSR + | OR + | AND + | XOR + | NOT + | COMPARE + | EQ + | NEQ + | LT + | GT + | LE + | GE + | SELF + | SELF_ADDRESS + | CONTRACT + | TRANSFER_TOKENS + | SET_DELEGATE + | CREATE_CONTRACT { ... } + | IMPLICIT_ACCOUNT + | VOTING_POWER + | NOW + | LEVEL + | AMOUNT + | BALANCE + | CHECK_SIGNATURE + | BLAKE2B + | KECCAK + | SHA3 + | SHA256 + | SHA512 + | HASH_KEY + | SOURCE + | SENDER + | ADDRESS + | CHAIN_ID + | TOTAL_VOTING_POWER + | PAIRING_CHECK + | SAPLING_EMPTY_STATE + | SAPLING_VERIFY_UPDATE + | TICKET + | READ_TICKET + | SPLIT_TICKET + | JOIN_TICKETS + ::= + | + | option + | list + | set + | operation + | contract + | ticket + | pair ... + | or + | lambda + | map + | big_map + | bls12_381_g1 + | bls12_381_g2 + | bls12_381_fr + | sapling_transaction + | sapling_state + ::= + | unit + | never + | bool + | int + | nat + | string + | chain_id + | bytes + | mutez + | key_hash + | key + | signature + | timestamp + | address + | option + | or + | pair ... + + +Reference implementation +------------------------ + +The language is implemented in OCaml as follows: + +- The lower internal representation is written as a GADT whose type + parameters encode exactly the typing rules given in this + specification. In other words, if a program written in this + representation is accepted by OCaml's typechecker, it is guaranteed + type-safe. This is of course also valid for programs not + handwritten but generated by OCaml code, so we are sure that any + manipulated code is type-safe. + + In the end, what remains to be checked is the encoding of the typing + rules as OCaml types, which boils down to half a line of code for + each instruction. Everything else is left to the venerable and well + trusted OCaml. + +- The interpreter is basically the direct transcription of the + rewriting rules presented above. It takes an instruction, a stack and + transforms it. OCaml's typechecker ensures that the transformation + respects the pre and post stack types declared by the GADT case for + each instruction. + + The only things that remain to be reviewed are value dependent + choices, such as we did not swap true and false when + interpreting the IF instruction. + +- The input, untyped internal representation is an OCaml ADT with + only 5 grammar constructions: ``String``, ``Int``, ``Bytes``, ``Seq`` and + ``Prim``. It is the target language for the parser, since not all + parsable programs are well typed, and thus could simply not be + constructed using the GADT. + +- The typechecker is a simple function that recognizes the abstract + grammar described in section X by pattern matching, producing the + well-typed, corresponding GADT expressions. It is mostly a checker, + not a full inferrer, and thus takes some annotations (basically the + input and output of the program, of lambdas and of uninitialized maps + and sets). It works by performing a symbolic evaluation of the + program, transforming a symbolic stack. It only needs one pass over + the whole program. + + Here again, OCaml does most of the checking, the structure of the + function is very simple, what we have to check is that we transform a + ``Prim ("If", ...)`` into an ``If``, a ``Prim ("Dup", ...)`` into a + ``Dup``, etc. diff --git a/docs/009/proof_of_stake.rst b/docs/009/proof_of_stake.rst new file mode 100644 index 0000000000000000000000000000000000000000..41b3de68647a3fef64fb20a4886a61f277dd1893 --- /dev/null +++ b/docs/009/proof_of_stake.rst @@ -0,0 +1,408 @@ +.. _proof-of-stake_009: + +Proof-of-stake in Tezos +======================= + +This document provides an in-depth description of the Tezos +proof-of-stake algorithm as implemented in the current protocol +(namely `PsCARTHA` on `mainnet`). + +Brief Overview +-------------- + +A blockchain is a linked list of **blocks**. In Tezos, blocks to be +added to the blockchain are agreed upon through a proof-of-stake +consensus mechanism. Proof-of-stake means that participants in the +consensus algorithm are chosen in function of their stake. In Tezos, a +participant needs to have a minimum stake of 8,000 ꜩ (which is +called a **roll**). If one does not have enough stake to participate +on its own or does not want to set up the needed infrastructure, (s)he +can use **delegation**. Therefore, in Tezos, participants in the +consensus algorithm are called **delegates**. There are two roles a +delegate can have: that of a **baker**, that is a delegate that +creates blocks, or that of an **endorser**, that is a delegate that +contributes in agreeing on a block by **endorsing** that block. + +**Baking rights** and **endorsing rights** are determined at the +beginning of a **cycle** (a chunk of blocks) by a follow-the-satoshi +strategy starting from a **random seed** computed from information +already found on the blockchain. + +To incentivize participation in the consensus algorithm, delegates are +**rewarded** for their baking and endorsing. As a counter-measure +against double-baking or double-endorsement a **security deposit** is +frozen from the delegate's account. The deposit is either released +after a number of cycles or burnt in case of proven bad behavior. + +The remainder of this document contains a detailed description of +the notions which are in bold in the text above. + +Further External Resources +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The original design of the proof-of-stake mechanism in Tezos can be +found in the `whitepaper +`_. +The following blog posts present the intuition behind the changes to the original consensus algorithm: + +- https://blog.nomadic-labs.com/analysis-of-emmy.html, +- https://blog.nomadic-labs.com/emmy-an-improved-consensus-algorithm.html, +- https://blog.nomadic-labs.com/a-new-reward-formula-for-carthage.html. + +Here are a few more resources that present Tezos' proof-of-stake +mechanism: + +- `Proof of Stake `_ +- `Liquid Proof-of-Stake `_ + +Please note that these external resources may contain outdated information. + +Blocks +------ + +The Tezos blockchain is a linked list of blocks. Blocks contain a +header and a list of operations. The header itself decomposes into a +shell header (common to all protocols) and a protocol-specific header. + +Shell header +~~~~~~~~~~~~ + +The shell header contains + +- ``level``: the height of the block, from the genesis block +- ``proto``: number of protocol changes since genesis (mod 256) +- ``predecessor``: the hash of the preceding block. +- ``timestamp``: the timestamp at which the block is claimed to have + been created. +- ``validation_pass``: number of validation passes (also number of + lists of lists of operations) +- ``fitness``: a sequence of sequences of unsigned bytes, ordered by + length and then lexicographically. It represents the claimed fitness + of the chain ending in this block. +- ``operations_hash``: the hash of a list of root hashes of Merkle + trees of operations. There is one list of operations per + validation pass. +- ``context`` Hash of the state of the context after application of + this block. + +Protocol header +~~~~~~~~~~~~~~~ + +- ``signature``: a digital signature of the shell and protocol headers + (excluding the signature itself). +- ``priority``: the position in the priority list of delegates at which + the block was baked. +- ``seed_nonce_hash``: a commitment to a random number, used to + generate entropy on the chain. Present in only one out of + ``BLOCKS_PER_COMMITMENT`` = 32 blocks. +- ``proof_of_work_nonce``: a nonce used to pass a low-difficulty + proof-of-work for the block, as a spam prevention measure. + +Block size +~~~~~~~~~~ + +Tezos does not download blocks all at once but rather considers +headers and various types of operations separately. Transactions are +limited by a total maximum size of 512kB (that is 5MB every 10 minutes +at most). + +Consensus operations (endorsements, denunciations, reveals) are +limited in terms of number of operations (though the defensive +programming style also puts limits on the size of operations it +expects). This ensures that critical operations do not compete with +transactions for block space. + +Fitness +~~~~~~~ + +To each block, we associate a measure of `fitness` which determines the +quality of the chain leading to that block. This measure is simply the +length of the chain (as in Bitcoin). More precisely, the fitness of a +block is 1 plus the fitness of the previous block. The shell changes +the head of the chain to the valid block that has the highest fitness. + +Cycles +------ + +Blocks in Tezos are grouped into *cycles* of +``BLOCKS_PER_CYCLE`` = 4,096 blocks. Since blocks are at least +``TIME_BETWEEN_BLOCKS[0]`` = one minute apart, this means a cycle lasts *at +least* 2 days, 20 hours, and 16 minutes. In the following description, +the current cycle is referred to as ``n``, it is the ``n``-th cycle from the +beginning of the chain. Cycle ``(n-1)`` is the cycle that took place +before the current one, cycle ``(n-2)`` the one before, cycle ``(n+1)`` +the one after, etc. + +At any point, the shell will not implicitly accept a branch whose +fork point is in a cycle more than ``PRESERVED_CYCLES`` = 5 cycles in the +past (that is *at least* 14 days, 5 hours, and 20 minutes). + +Delegation +---------- + +Tezos uses a delegated proof-of-stake model. The acronym DPOS has come to +designate a specific type of algorithm used, for instance in Bitshares. +This is *not* the model used in Tezos, though there is a concept +of delegation. + +Delegates +~~~~~~~~~ + +Tokens are controlled through a private key called the +*manager key*. Tezos accounts let the manager specify a public +delegate key. This key may be controlled by the managers themselves, or +by another party. The responsibility of the delegate is to take part in +the proof-of-stake consensus algorithm and the governance of Tezos. + +The manager can generally change the delegate at any time, though +contracts can be marked to specify an immutable delegate. Though +delegation can be changed dynamically, the change only becomes effective +after a few cycles. + +There are also default accounts in Tezos, which are just the hash of the +public key. These accounts do not have an attached delegate key and do +not participate in the proof-of-stake algorithm. + +Finally, delegate accounts (used for placing safety deposits) are +automatically delegated to the delegate itself. + +Active and passive delegates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A delegate can be marked as either active or passive. A passive delegate +cannot be selected for baking or endorsing. + +A delegate becomes passive for cycle ``n`` when they fail to create +any blocks or endorsements in the past ``PRESERVED_CYCLES`` +cycles, that is, in cycles ``n-1``, ``n-2``, ..., ``n - +PRESERVED_CYCLES``. + +Discussion: giving ``PRESERVED_CYCLES`` a small value means +the chain adapts more quickly to participants disappearing. It's not +unlike the "difficulty adjustment" of Bitcoin. However, a long value +would ensure that a minority fork progresses more slowly for a longer +period of time than the majority fork. ``PRESERVED_CYCLES`` +gives the majority chain a "headstart". + +Rolls +~~~~~ + +In theory, it would be possible to give each token a serial number +and track the specific tokens assigned to specific delegates. However, +it would be too demanding of nodes to track assignments at such a +granular level. Instead, we introduce the concept of rolls. A *roll* +represents a set of coins delegated to a given key. A roll holds +``TOKENS_PER_ROLL`` = 8,000 tokens. When tokens are moved, or a +delegate for a contract is changed, the rolls change delegate +according to the following algorithm. + +Each delegate has a stack of roll identifiers plus some "change" which is always +an amount smaller than ``TOKENS_PER_ROLL``. When tokens are moved from +one delegate to the other, first, the change is used. If it is not +enough, rolls need to be "broken" which means that they move from the +delegate stack to a global, unallocated, roll stack. This is done until +the amount is covered, and some change possibly remains. + +Then, the other delegate is credited. First, the amount is added to the +"change". If it becomes greater than ``TOKENS_PER_ROLL``, then rolls +are unstacked from the global unallocated roll stack onto the delegate +stack. If the global stack is empty, a fresh roll is created. + +This preserves the property that if the delegate is changed through +several transactions, the roll assignment is preserved, even if each +operation moves less than a full roll. + +The advantage of tracking tokens in this way is that a delegate creating +a malicious fork cannot easily change the specific rolls assigned to +them, even if they control the underlying tokens and shuffle them +around. + +Roll snapshots +~~~~~~~~~~~~~~ + +Roll snapshots represent the state of rolls for a given block. Roll +snapshots are taken every ``BLOCKS_PER_ROLL_SNAPSHOT`` = 256 blocks, +which is 16 times per cycle. There is a tradeoff between memory +consumption and economic efficiency. If roll snapshots are too frequent, +they will consume a lot of memory. If they are too rare, strategic +participants could purchase many tokens in anticipation of a snapshot +and resell them right after. + +Baking +~~~~~~ + +Baking is the action of producing and signing a block. +In Bitcoin, the right to produce a block is associated with solving a +proof-of-work puzzle. In Tezos, the right to produce a block in +cycle ``n`` is assigned to a randomly selected roll in a randomly +selected roll snapshot from cycle ``n-PRESERVED_CYCLES-2``. + +We admit, for the time being, that the protocol generates a random +seed for each cycle. From this random seed, we can seed a +cryptographically secure pseudo-random number generator which is used +to draw baking rights for a cycle. + +Each level is associated with a priority list of delegates. +This list is obtained by randomly selecting an active roll for each +position in the list, and then taking the owner of the selected roll. +As the draw is independent for each list position, it is possible that +the same public key appears multiple times in this list. +The first baker in the list is the first one who can bake a block at +that level. +If a delegate is for some reason unable to bake, the next delegate in +the list can step up and bake the block. +The elements of the list that contain a certain delegate are also +called the *baking slots* of that delegate, and the indexes of these +slots are called *priorities*. + +Baking a block gives a block reward (detailed below) plus +all fees paid by transactions inside the block. + +Endorsements +~~~~~~~~~~~~ + +To each level, we associate a list of ``ENDORSERS_PER_BLOCK`` = +32 *endorsers*. Endorsers are drawn similarly as bakers, by randomly +selecting 32 active rolls with replacement. + +Each endorser verifies the last block that was baked, say at the level +``n``, and emits an endorsement operation. The endorsement operations +are then baked in block ``n+1``. Once block ``n+1`` is baked, no other +endorsement for block ``n`` will be considered valid. + +An endorser may have more than one endorsement +slot. However, the endorser injects a single endorsement operation, +which represents all of its endorsement slots. In what follows, when +we say "the number of endorsements a block contains", we do not refer +to the number of endorsement operations, but to the number of +endorsement slots covered by the contained endorsement +operations. (In the code base, the number of filled endorsement slots +is called the block's endorsing power.) + +Minimal block delays +~~~~~~~~~~~~~~~~~~~~ + +A block is valid only if its timestamp has a minimal delay with +respect to the previous block’s timestamp. The minimal delay is given +by the following expression: ``TIME_BETWEEN_BLOCKS[0] + +TIME_BETWEEN_BLOCKS[1] * p +`` ``DELAY_PER_MISSING_ENDORSEMENT * MAX +(0, INITIAL_ENDORSERS - e)`` where ``TIME_BETWEEN_BLOCKS[0]`` = 60 +seconds, ``TIME_BETWEEN_BLOCKS[1]`` = 40 seconds, +``DELAY_PER_MISSING_ENDORSEMENT`` = 8 seconds, ``INITIAL_ENDORSERS`` = +24, ``p`` is the block's priority at which the block was baked, and +``e`` is the number of endorsements the block contains. That is, the +higher the priority and the fewer endorsements a block carries the +longer it takes before it can be considered valid. However, if the +block contains more than ``INITIAL_ENDORSERS`` then there is no time +penalty. + +Rewards +~~~~~~~ + +Baking a block gives a block reward of ``e * +BAKING_REWARD_PER_ENDORSEMENT[p']`` plus all fees paid by the +transactions contained in the block, where +``BAKING_REWARD_PER_ENDORSEMENT`` = ``[1.250ꜩ, 0.1875ꜩ]``, +``e`` is the number of endorsements the block contains, ``p`` is the +priority at which the block was baked, and ``p'`` is 0 if ``p`` is +0 and is 1 if ``p`` is bigger than 0. That is, a delegate +producing a block of priority 0 will be rewarded ``e * 1.25`` +ꜩ. If a delegate produces a block at priority 1 or higher, then +the reward is ``e * 0.1875`` ꜩ. + +Endorsers also receive a reward (at the same time as block creators +do). The reward is ``ENDORSEMENT_REWARD[p']``, where +``ENDORSEMENT_REWARD`` = ``[1.250ꜩ, 0.833333ꜩ]``, where ``p'`` +is as above. That is, a delegate endorsing a block of priority 0 +will be rewarded ``e * 1.25`` ꜩ, with ``e`` the number of endorsement +slots attributed to the delegate for this level. Moreover, endorsing +blocks of priority 1 or higher will be rewarded ``e * 0.8333333`` +ꜩ. + +Security deposits +~~~~~~~~~~~~~~~~~ + +The cost of a security deposit is ``BLOCK_SECURITY_DEPOSIT`` = 512 ꜩ +per block created and ``ENDORSEMENT_SECURITY_DEPOSIT`` = 64 ꜩ per +endorsement slot. + +Each delegate key has an associated security deposit account. +When a delegate bakes or endorses a block the security deposit is +automatically moved to the deposit account where it is frozen for +``PRESERVED_CYCLES`` cycles, after which it is automatically moved +back to the baker's main account. + +Since deposits are locked for a period of ``PRESERVED_CYCLES`` one can +compute that at any given time, about ((``BLOCK_SECURITY_DEPOSIT`` + +``ENDORSEMENT_SECURITY_DEPOSIT`` \* ``ENDORSERS_PER_BLOCK``) \* +(``PRESERVED_CYCLES`` + 1) \* ``BLOCKS_PER_CYCLE``) tokens of all +staked tokens should be held as security deposits. For instance, if +the amount of staked tokens is 720,000,000 ꜩ, then roughly 8.74% of +this amount is stored in security deposits. This percentage also gives +an indication of the minimal amount of tokens a delegate should own in +order to not miss out on creating a block or an endorsement. Please +refer to `this section +`_ +of the documentation for a discussion on (over-)delegation. + +Inflation +~~~~~~~~~ + +Inflation from block rewards and endorsement reward is at most +``ENDORSERS_PER_BLOCK`` \* (``ENDORSEMENT_REWARD[0]`` + +``BAKING_REWARD_PER_ENDORSEMENT[0]``) = +80 ꜩ. This means at most 5.51% annual inflation. + +Random seed +~~~~~~~~~~~ + +Each cycle ``n`` is associated with a random seed. This seed is used to +randomly select a roll snapshot from cycle ``n-2`` and to randomly +select rolls in the selected snapshot. The selected rolls determine +the baking and endorsing rights in cycle ``n+PRESERVED_CYCLES``. + +The random seed for cycle ``n`` is a 256-bit number generated at the +very end of cycle ``n-1`` from nonces to which delegates commit during +cycle ``n-2``. One out of every ``BLOCKS_PER_COMMITMENT`` = 32 blocks +can contain a commitment. There are therefore at most +``BLOCKS_PER_CYCLE / BLOCKS_PER_COMMITMENT`` = 128 commitments. A +commitment is the hash of a nonce. The commitment is generated by the +baker who produces the block and is included in the block header. + +The committed nonce must be revealed by the original baker during +cycle ``n-1`` under penalty of forfeiting the rewards and fees of the +block that included the commitment. The associated security deposit is +not forfeited. + +A *nonce revelation* is an operation, and multiple nonce revelations +can thus be included in a block. A baker receives a +``SEED_NONCE_REVELATION_TIP`` = 1/8 ꜩ reward for including a +revelation. Revelations are free operations which do not compete with +transactions for block space. Up to ``MAX_ANON_OPS_PER_BLOCK`` = 132 +revelations, wallet activations and denunciations can be contained in any +given block. + +The seed for cycle ``n`` is obtained as follows: the seed of cycle +``n-1`` is hashed with a constant and then with each nonce revealed in +cycle ``n-1``. + +Accusations +----------- + +If two endorsements are made for the same slot or two blocks at the +same height by a delegate, the evidence can be collected by an accuser +and included in a block for a period of ``PRESERVED_CYCLES``, +including the current cycle. + +This accusation forfeits the entirety of the safety deposit and future +reward up to that point in the cycle. Half is burned, half goes to the +accuser in the form of a block reward. + +In the current protocol, accusations for the *same* incident can be +made several times after the fact. This means that the deposits and +rewards for the entire cycle are forfeited, including any deposit +made, or reward earned, after the incident. + +Pragmatically, any baker who either double bakes or endorses in a +given cycle should immediately stop both baking and endorsing for the +rest of that cycle. diff --git a/docs/009/sapling.rst b/docs/009/sapling.rst new file mode 100644 index 0000000000000000000000000000000000000000..549403dd4b45d58bb8245dc558bb6f27a5b5b068 --- /dev/null +++ b/docs/009/sapling.rst @@ -0,0 +1,498 @@ +.. _sapling_dev_009: + +**The features described in this page are experimental and have not undergone any security review.** + +Sapling integration +=================== + +Sapling is a protocol enabling privacy-preserving transactions of fungible +tokens in a decentralised +environment. It was designed and implemented by the Electric Coin +Company as the last iteration over a series of previous protocols and +academic works starting with the `Zerocoin seminal +paper `_. + +The reference implementation of Sapling, +`librustzcash `_, was +integrated in the Tezos codebase during 2019. It will be proposed as +part of a protocol amendment during 2020. + +Librustzcash and the Tezos integration implement the protocol +described in this `specification +`_, version 2020.1.0. + + +Sapling +------- + +Keys +~~~~ + +Sapling offers a rich set of keys, each allowing different operations. +A `spending key` allows to spend tokens so if it is lost or +compromised the tokens could remain locked or be stolen. +From a spending key it is possible to derive a corresponding `viewing +key` which allows to view all incoming and outgoing transactions. +The viewing key allows the owner of the tokens to check their balance +and transaction history so if compromised there is a complete loss of +privacy. +On the other hand a viewing key can willingly be shared with a third +party, for example with an auditor for regulatory compliance purposes. + +A viewing key can also derive several diversified `addresses`. +An address can be used to receive funds, much like the address of an +implicit account. + +Additionally `proving keys` can be used to allow the creation of proofs, +thus revealing private information, without being able to spend funds. +They are useful for example in case the spending key is stored in a +hardware wallet but we'd like to use our laptop to craft the +transaction and produce the zero-knowledge proofs, which are +computationally too intensive for an embedded device. + +More details can be found in the `specification document +`_. + +Shielded transactions +~~~~~~~~~~~~~~~~~~~~~ + +Transactions use Bitcoin's UTXO model with the important difference that each +input and output, instead of containing an amount and an address, +are just cryptographic `commitments`. +In order to avoid double spends, it's important to be able to check +that a commitment has not already been spent. In Bitcoin we just need to +check if an output is also later used as an input to verify if it's +already spent. In Sapling however we can't know because inputs are not +linked to outputs. +For this reason for each input of a transaction, the owner must also +publish a `nullifier`, which invalidates it. The nullifier can only be +produced by the owner of a commitment and it's deterministic so that +everybody can check that it hasn't been already published. +Note however that it is not possible to infer which commitment has +been nullified. +Transactions of this form are privacy preserving and are referred to +as `shielded`, because they reveal neither the amount, the sender nor +the receiver. + +The existing set of transactions is referred to as the `shielded pool`. +Unlike Bitcoin, where everybody can compute the set of unspent +outputs of every user, in Sapling only the owner of a viewing key can +find their outputs and verify that they are not already spent. +For this reason, to an external +observer, the shielded pool is always increasing in size and the more +transactions are added the harder it is to pinpoint the commitments +belonging to a user. + +When we spend a commitment there is some additional information that +we need to transmit to the recipient in order for them to spend the +corresponding output. +This data is encrypted under a symmetric key resulting from a +Diffie-Hellman key exchange using the recipient address and an +ephemeral key. +In principle this `ciphertext` can be transmitted off-chain as it's +not needed to verify the integrity of the pool. For convenience, in +Tezos, it is stored together with the commitment and the nullifier on +chain. + +For reasons of efficiency the commitments are stored in an incremental +`Merkle tree `_ which +allows for compact proofs of membership. The root of the tree is all +that is needed to refer to a certain state of the shielded pool. + +In order to ensure the correctness of a transaction, given that there +is information that we wish to remain secret, the spender must also +generate proofs that various good properties are true. +Thanks to the use of `SNARKs `_ +these proofs are very succinct in size, fast to verify and they don't +reveal any private information. + +This model of transaction adapts elegantly to the case when we need to +mint or burn tokens, which is needed to shield or unshield from a +transparent token. +It suffices to add more values in the outputs than in the inputs +to mint and to have more in inputs than outputs to burn. + +Privacy guarantees +~~~~~~~~~~~~~~~~~~ + +We explained that the shielded pool contains one commitment for each +input (spent or not), and one nullifier for each spent input. +These cryptographic commitments hide the amount and the owner of the +tokens they represent. +Additionally commitments are unlinkable meaning that we can not deduce +which input is spent to create an output. + +It should be noted that the number of inputs and outputs of a +transaction is public, which could help link a class of +transactions. This problem can be mitigated by adding any number of +dummy inputs or outputs at the cost of wasting some space. + +The shielded pool communicates with the public ledger by minting and +burning shielded tokens in exchange for public coins. +Therefore going in and out of the shielded pool is public: we know +which address shielded or unshielded and how much. +We can among other things infer the total number of shielded coins. + +Timing and network information can also help to deduce some private +information. +For example by observing the gossip network we might learn the IP +address of somebody that is submitting a shielded transaction. +This can be mitigated by using `TOR +`_. + +Good practices +~~~~~~~~~~~~~~ + +When blending in a group of people, one should always pay attention to +the size and the variety of the group. + +We recommend two good practices. First, do not originate a second +contract if another one has the same functionalities, it will split +the anonymity set. + +Second, remember that shielding and unshielding are public operations. +A typical anti-pattern is to shield from tz1-alice 15.3 tez, and then +unshield 15.3 tez to tz1-bob. It's fairly clear from timing and +amounts that Alice transferred 15.3 tez to Bob. +To decorrelate the two transfers it is important to change the +amounts, let some time pass between the two and perform the +transactions when there is traffic in the pool. +Similar problems exist in ZCash and they are illustrated in this +introductory `blog post +`_. + +There are a number of more sophisticated techniques to deanonymise +users using timing of operations, network monitoring, side-channels on +clients and analysis of number of inputs/outputs just to mention a few +(`A fistful of Bitcoins +`_ is a good +first read). +We advice users to be familiar with the use of the TOR network and to +use clients developed specifically to protect their privacy. + + +Tezos integration +----------------- + +Michelson: verify update +~~~~~~~~~~~~~~~~~~~~~~~~ + +We introduce two new Michelson types `sapling_state` and +`sapling_transaction`, and two instructions called +`SAPLING_VERIFY_UPDATE` and `SAPLING_EMPTY_STATE` +(see the :ref:`Michelson reference` +for more details). +`SAPLING_EMPTY_STATE` pushes an empty `sapling_state` on the stack. +`SAPLING_VERIFY_UPDATE` takes a transaction and a state and returns an +option type which is Some (updated +state and a balance) if the transaction is correct, None otherwise. +A transaction has a list of inputs, outputs, a signature, a balance, +and the root of the Merkle tree containing its inputs. +The verification part checks the zero-knowledge proofs of all inputs +and outputs of the transaction, which guarantee several properties of +correctness. +It also checks a (randomised) signature associated with each input +(which guarantees that the owner forged the transaction), and the +signature that binds the whole transaction together and guarantees the +correctness of the balance. +All the signatures are over the hash of the data that we wish to sign +and the hash function used is Blake2-b, prefixed with the anti-replay string. +The anti-replay string is the the concatenation of the chain id and +the smart contract address. The same string has to be used by the client for +signing. + +Verify_update also checks that the root of the Merkle tree appears in +one of the past states and that the nullifiers are not already +present (i.e. no double spending is happening). +If one of the checks fails the instruction returns None. + +Otherwise the function adds to the new state the nullifiers given with each inputs +and adds the outputs to the Merkle tree, which will produce a new root. +It should be noted that it is possible to generate transactions +referring to an old root, as long as the inputs used were present in +the Merkle tree with that root and were not spent after. +In particular the protocol keeps 120 previous roots and guarantees +that roots are updated only once per block. +Considering 1 block per minute and that each block contains at least +one call to the same contract, a client has 2 hours to have its +transaction accepted before it is considered invalid. + +The nullifiers are stored in a set. The ciphertexts and other relevant +information linked to the commitment of the Merkle tree are +stored in a map indexed by the position of the commitment in the +Merkle tree. + +Lastly the instruction pushes the updated state and the balance as an option +on the stack. + +Example contracts +~~~~~~~~~~~~~~~~~ + +Shielded tez +^^^^^^^^^^^^ + +An example contract to have a shielded tez with a 1 to 1 conversion to +tez is available in the tests of `lib_sapling`. + +Simple Vote Contract +^^^^^^^^^^^^^^^^^^^^ + +One might think to use Sapling to do private voting. +It is possible to adapt shielded transactions to express preferences. +**Note that this is not what Sapling is designed for and it doesn't provide the same properties as an actual private voting protocol.** +A natural naive idea is the following. +Suppose we want a set of users to express a preference for option A or +B, we can generate two Sapling keys with two addresses that are +published and represent the two options. +The contract lets each user create a token which represents one vote +that can then be transferred to address A or B. +Using the published viewing keys everyone can check the outcome of the +vote. +**However note that a transaction can be replayed and we can see the balance of A or B going up. +This system does not offer ballot privacy. +Therefore one should ensure that the vote he is casting cannot be linked to him. +It is possible that the practical situation makes this usable but we recommend in general not to use +it for any important vote.** +Note that using a random elliptic curve element as incoming viewing key allows to generate a +dummy address that cannot be spent. This eases the counting of the votes. +To ensure that the ivk does not correspond to a normal address with spending key, one +can use the Fiat-Shamir heuristic. + + +Fees issue +~~~~~~~~~~ + +We have an additional privacy issue that Z-cash doesn't have. When +interacting with a shielded pool we interact with a smart contract +with a normal transaction and therefore have to pay fees from an +implicit account. +One could guess that private transactions whose fees are paid by the +same implicit account are from the same user. +This can be mitigated by making a service that act as a proxy by +forwarding the user transactions and paying it fees. The user would +then include in the transaction a shielded output for the service that +covers the fees plus a small bonus to pay the service. +This output can be open by the service before sending the transaction +to check that there is enough money to cover its fees. As for Z-cash, +users interacting with the proxy should use TOR or mitigate network +analysis as they wish. + +Gas, storage and costs +~~~~~~~~~~~~~~~~~~~~~~ + +Gas evaluation is not yet done. + +RPCs +~~~~ + +There are two Sapling RPCs under the prefix `context/sapling`. +`get_size` returns a pair with the size of the set of commitments +and the size of the set of nullifiers. +`get_diff` takes two optional starting offsets `cm_from` and `nf_from` +and returns the sapling state that was added from the offsets to the +current size. In particular it returns three lists, commitments, +ciphertexts from position `cm_from` up to the last one added and +nullifiers, from `nf_from` to the last one added. +Additionally it returns the last computed root of the merkle tree so +that a client updating its tree using the diff can verify the +correctness of the result. + +Client +~~~~~~ + +Wallet +^^^^^^ + +tezos-client supports Sapling keys and can send +shielded transactions to smart contracts. + +The client supports two ways to generate a new Sapling spending key. +It can be generated from a mnemonic using `BIP39 +`_, so +that it can be recovered in case of loss using the mnemonic. +Alternatively it is possible to derive new keys from existing ones +using `ZIP32 +`_, a Sapling +variant of `BIP32 +`_ for +hierarchical deterministic wallets. As usual, in this case it is +important to note the derivation path of the key to be able to recover +it in case of loss. +At the moment there is no hardware wallet support, keys are stored in +`~/.tezos-client/sapling_keys` by default encrypted with a password. +**Users should take care to backup this file.** + +The client can also derive addresses from viewing keys. +By default addresses are generated using an increasing counter called +the address index. Not all indexes corresponds to valid addresses for +each key so it is normal to see an increasing counter that +occasionally skips a few position. + +Because for now the only support for Sapling keys is to interact with +smart contracts, the client binds each newly generated key to a +specific smart contract address. + +Operations +^^^^^^^^^^ + +The client also facilitates the creation of shielded transactions and +their transfer as arguments of smart contracts. +For now there is seamless integration to send transactions to the +reference shielded-tez contract and we are planning to support a +larger class of contracts. + +For the shielded-tez smart contract, the client supports shielding, +unshielding and shielded transactions. +In the case of shielded transactions there are two commands, one to +forge a transaction and save it to file and one to submit it to the +smart contract. +The idea is that a user should not use their own transparent tz{1,2,3} +address to submit a shielded address but rather have a third party +inject it. + +Message argument +^^^^^^^^^^^^^^^^ +Sapling also allows to send an arbitrary encrypted message attached +to an output. +The message size has to be fixed by pool for privacy reasons. +For now it is fixed overall at eight bytes. An incorrect message length +will raise a failure in our client and the protocol will reject the +transaction. Our client adds a default zero's filled message of the +right length. If a message is provided with the --message option, +the client will pad it or truncate it if necessary. A warning message +is printed only if the user's message is truncated. + + +Code base +~~~~~~~~~ + +The current code-base is organized in three main components. +There is a core library called `lib_sapling` which binds `librustzcash`, +adds all the data structures necessary to run the sapling +protocol and includes a simple client and baker. +Under the protocol directory there is a `lib_client_sapling` library +which implements a full client capable of handling Sapling keys and +forging transactions. +Lastly in the protocol there is a efficient implementation of the +Sapling storage, in the spirit of `big_map`s, and the integration of +`SAPLING_VERIFY_UPDATE` in the Michelson interpreter. + +Protocol +^^^^^^^^ + +In order to export the Sapling library to the protocol we first need +to expose it through the environment that sandboxes the protocol. +The changes under `src/lib_protocol_environment` are simple but very +relevant as any change of the environment requires a manual update of the +Tezos node. This changes are part of version V1 of the environment +while protocols 000 to 006 depends on version V0. + +There are two main changes to Tezos' economic protocol, the storage +for Sapling and the addition of `SAPLING_VERIFY_UPDATE` to the Michelson +interpreter. + +Given that the storage of a Sapling contract can be substantially +large, it is important to provide an efficient implementation. +Similarly to what it's done for big_maps, the storage of Sapling can't +be entirely deserialized and modified in memory but only a diff of the +changes is kept by the interpreter and applied at the end of each +smart contract call. + +In the Michelson interpreter two new types are added, `sapling_state` and +`sapling_transaction`, and the instruction `SAPLING_VERIFY_UPDATE`. + +Client +^^^^^^ + +Under `lib_client_sapling` there is the client integration +with the support for Sapling keys and forging of transactions. +The main difference from the existing Tezos client is the need for the +Sapling client to keep an additional state, for each contract. +Because Sapling uses a UTXO model it is necessary for a client to +compute the set of unspent outputs in order to forge new transactions. +Computing this set requires scanning all the state of a contract which +can be expensive. +For this reason the client keeps a local state of the unspent outputs +after the last synchronization and updates it before performing any +Sapling command. +The update is done using the RPCs to recover the new updates since the +last known position. + +The state of all sapling contracts is stored in +`~/.tezos-client/sapling_states`. This file can be regenerated from +the chain in case of loss. However disclosure of this file will reveal +the balance and the unspent outputs of all viewing keys. + +Memo +^^^^^^ + +Sapling offers the possibility to add an arbitrary memo to any +created output. The memo is encrypted and available to anyone +owning the outgoing viewing key or the spending key. +For privacy reasons the size of the memo is fixed per contract +and it is chosen at origination time. +A transaction containing an output with a different memo-size +will be rejected. + +Sandbox tutorial +~~~~~~~~~~~~~~~~ + +As usual it's possible to test the system end-to-end using the +:ref:`sandboxed-mode`. +After having set up the sandbox and originated the contract, a good +way to get familiar with the system is to generate keys and then +perform the full cycle of shielding, shielded transfer and +unshielding. + +:: + + # set up the sandbox + ./src/bin_node/tezos-sandboxed-node.sh 1 --connections 0 & + eval `./src/bin_client/tezos-init-sandboxed-client.sh 1` + tezos-activate-alpha + + # originate the contract with its initial empty sapling storage, + # bake a block to include it. + # { } represents an empty Sapling state. + tezos-client originate contract shielded-tez transferring 0 from bootstrap1 \ + running src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract.tz \ + --init '{ }' --burn-cap 3 & + tezos-client bake for bootstrap1 + + # as usual you can check the tezos-client manual + tezos-client sapling man + + # generate two shielded keys for Alice and Bob and use them for the shielded-tez contract + # the memo size has to be indicated + tezos-client sapling gen key alice + tezos-client sapling use key alice for contract shielded-tez --memo-size 8 + tezos-client sapling gen key bob + tezos-client sapling use key bob for contract shielded-tez --memo-size 8 + + # generate an address for Alice to receive shielded tokens. + tezos-client sapling gen address alice + zet1AliceXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # Alice's address + + + # shield 10 tez from bootstrap1 to alice + tezos-client sapling shield 10 from bootstrap1 to zet1AliceXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX using shielded-tez --burn-cap 2 & + tezos-client bake for bootstrap1 + tezos-client sapling get balance for alice in contract shielded-tez + + # generate an address for Bob to receive shielded tokens. + tezos-client sapling gen address bob + zet1BobXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # Bob's address + + # forge a shielded transaction from alice to bob that is saved to a file + tezos-client sapling forge transaction 10 from alice to zet1BobXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX using shielded-tez + + # submit the shielded transaction from any transparent account + tezos-client sapling submit sapling_transaction from bootstrap2 using shielded-tez --burn-cap 1 & + tezos-client bake for bootstrap1 + tezos-client sapling get balance for bob in contract shielded-tez + + # unshield from bob to any transparent account + tezos-client sapling unshield 10 from bob to bootstrap1 using shielded-tez --burn-cap 1 + ctrl+z # to put the process in background + tezos-client bake for bootstrap1 + fg # to put resume the transfer diff --git a/docs/009/voting.rst b/docs/009/voting.rst new file mode 100644 index 0000000000000000000000000000000000000000..bb4afa3879b19ad103ee6950d41e5c797965b28d --- /dev/null +++ b/docs/009/voting.rst @@ -0,0 +1,193 @@ +The Voting Process +================== + +The design of the Tezos Node allows the consensus protocol to be +amended, that is replaced by another set of OCaml files which +implement the API of a valid protocol. + +In the current protocol the amendment procedure is guided by a voting +procedure where delegates can propose, select and test a candidate +protocol before activating it. +Delegates take part in the amendment procedure with an influence +proportional to their stake, one roll one vote. + +The procedure consists of five periods, each of 20480 blocks (or +~two weeks), for a total of approximately 2 months and a half. + +Other than this page, there is an excellent overview from `Jacob +Arluck on medium. +`_ + +Periods +------- + +The voting procedure works as follows: + +- `Proposal period`: delegates can submit protocol amendment proposals using + the `proposals` operation. At the end of a proposal period, the proposal with + most supporters is selected and we move to a exploration period. + If there are no proposals, or a tie between proposals, a new proposal + period starts. Each delegate can submit a maximum of 20 proposals, + including duplicates. +- `Exploration period`: delegates can cast one vote to pursue the + voting process or not with the winning proposal using the `ballot` + operation. At the end of a exploration period if participation + reaches the quorum and the proposal has a super-majority in favor, + we proceed to a cooldown period. Otherwise we go back to a proposal + period. +- `Cooldown period`: The only purpose of this period is to let some + time elapse before the promotion period. +- `Promotion period`: delegates can cast one vote to promote or not + the proposal using the `ballot` operation. At the end of a + promotion period if participation reaches the quorum and the + proposal has a super-majority in favor, we proceed to adoption + period. Otherwise we go back to a proposal period. +- `Adoption period`: at the end of the period the proposal is activated + as the new protocol and we go back to a proposal period. + +Each of the periods above are called a `voting period`. It is important to note +that the stake of each delegate is computed at the beginning of each voting +period, and if the delegate owns one roll or more, its stake in number of rolls is +stored in a list called the `voting listings`. + +Super-majority and Quorum +------------------------- + +Both voting periods work in the same way, only the subject of the +vote differs. +During a vote a delegate can cast a single Yea, Nay or Pass vote. +A vote is successful if it has super-majority and the participation +reaches the current quorum. + +`Super-majority` means the Yeas are more than 8/10 of Yeas+Nays votes. +The `participation` is the ratio of all received votes, including +passes, with respect to the number of possible votes. The `quorum` +starts at 80% and at each vote it is updated using the old quorum and +the current participation with the following coefficients:: + + newQ = oldQ * 8/10 + participation * 2/10 + +More details can be found in the file +``src/proto_009_PsFLoren/lib_protocol/amendment.ml``. + +Operations +---------- + +There are two operations used by the delegates: ``proposals`` and ``ballot``. +A proposal operation can only be submitted during a proposal period. + +:: + + Proposals : { + source: Signature.Public_key_hash.t ; + period: Voting_period_repr.t ; + proposals: Protocol_hash.t list ; } + +Source is the public key hash of the delegate, period is the unique +identifier of each voting period and proposals is a non-empty list of +maximum 20 protocol hashes. +The operation can be submitted more than once but only as long as the +cumulative length of the proposals lists is less than 20. +Duplicate proposals from the same delegate are accounted for in the +maximum number of proposals for that delegate. +However duplicates from the same delegate are not tallied at the end +of the proposal period. + +For example, a delegate submits a proposals operation for protocol A +and B early in the proposal period, later a new protocol C is revealed +and the delegate submits another proposals operation for protocol B +and C. +The list of submissions that will be tallied is [A,B,C] and the + +A ballot operation can only be submitted during one of the voting +periods, and only once per period. + +:: + + Ballot : { + source: Signature.Public_key_hash.t ; + period: Voting_period_repr.t ; + proposal: Protocol_hash.t ; + ballot: Vote_repr.ballot ; } + +Source and period are the same as above, while proposal is the +currently selected proposal and ballot is one of ``Yea``, ``Nay`` or +``Pass``. +The pass vote allows a delegate to not influence a vote but still +allowing it to reach quorum. + +More details can be found, as for all operations, in +``src/proto_009_PsFLoren/lib_protocol/operation_repr.ml``. +The binary format is described by ``tezos-client describe unsigned +operation``. + +Client Commands +--------------- + +Tezos' client provides a command to show the status of a voting period. +It displays different informations for different kind of periods, as +in the following samples:: + + $ tezos-client show voting period + Current period: "proposal" + Blocks remaining until end of period: 59 + Current proposals: + PsNa6jTtsRfbGaNSoYXNTNM5A7c3Lji22Yf2ZhpFUjQFC17iZVp 400 + + $ tezos-client show voting period + Current period: "exploration" + Blocks remaining until end of period: 63 + Current proposal: PsNa6jTtsRfbGaNSoYXNTNM5A7c3Lji22Yf2ZhpFUjQFC17iZVp + Ballots: { "yay": 400, "nay": 0, "pass": 0 } + Current participation 20.00%, necessary quorum 80.00% + Current in favor 400, needed supermajority 320 + + $ tezos-client show voting period + Current period: "cooldown" + Blocks remaining until end of period: 64 + Current proposal: PsNa6jTtsRfbGaNSoYXNTNM5A7c3Lji22Yf2ZhpFUjQFC17iZVp + +It should be noted that the number 400 above is a number of rolls. +The proposal has a total of 400 rolls, which may come from several +delegates. The same applies for the ballots, there are 400 rolls in +favor of testing protocol PsNa6jTt. + +Submit proposals +~~~~~~~~~~~~~~~~ + +During a proposal period, the list of proposals can be submitted with:: + + tezos-client submit proposals for ... + +Remember that each delegate can submit a maximum of 20 protocol +hashes including duplicates. +Moreover each proposal is accepted only if it meets one of the +following two conditions: + +- the protocol hash was already proposed on the network. In this case + we can submit an additional proposal that "upvotes" an existing one + and our rolls are added to the ones already supporting the proposal. +- the protocol is known by the node. In particular the first proposer + of a protocol should be able to successfully inject the protocol in + its node which performs some checks, compiles and loads the + protocol. + +Submit ballots +~~~~~~~~~~~~~~ + +During a voting period, being it an exploration or a promotion period, +ballots can be submitted once with:: + + tezos-client submit ballot for + +Other resources +~~~~~~~~~~~~~~~ + +For more details on the client commands refer to the manual at +:ref:`client_manual_009`. + +For vote related RPCs check the :ref:`rpc_index_009` under the prefix +``vote/``. + +For Ledger support refer to Obsidian Systems' `documentation +`_. diff --git a/docs/Makefile b/docs/Makefile index ea0264d4e1bc12297f68d7a0dfb7653cb75a6a37..a4cf28d4e4c1a6e665eac5aa5b3ce5fa73bf349e 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -9,13 +9,15 @@ DOCGENDIR = doc_gen DOCERRORDIR = $(DOCGENDIR)/errors DOCRPCDIR = $(DOCGENDIR)/rpcs -ALPHA_LONG = ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK -EDO_LONG = PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA -DELPHI_LONG = PsDELPH1Kxsxt8f9eWbxQeRxkjfbxoqM52jvs5Y5fBxWWh4ifpo +ALPHA_LONG = ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK +FLORENCE_LONG = PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i +EDO_LONG = PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA +DELPHI_LONG = PsDELPH1Kxsxt8f9eWbxQeRxkjfbxoqM52jvs5Y5fBxWWh4ifpo -ALPHA_SHORT = alpha -EDO_SHORT = 008-PtEdo2Zk -DELPHI_SHORT = 007-PsDELPH1 +ALPHA_SHORT = alpha +FLORENCE_SHORT = 009-PsFLoren +EDO_SHORT = 008-PtEdo2Zk +DELPHI_SHORT = 007-PsDELPH1 SCRIPTSDIR = scripts CHECKXREFS = $(SCRIPTSDIR)/check_proto_xrefs.py @@ -31,6 +33,11 @@ manuals: main @../tezos-baker-$(ALPHA_SHORT) man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > alpha/tezos-baker-alpha.html @../tezos-endorser-$(ALPHA_SHORT) man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > alpha/tezos-endorser-alpha.html @../tezos-accuser-$(ALPHA_SHORT) man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > alpha/tezos-accuser-alpha.html + # 009 (Florence) protocol + @../tezos-client -protocol $(FLORENCE_LONG) man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > 009/tezos-client-009.html + @../tezos-baker-$(FLORENCE_SHORT) man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > 009/tezos-baker-009.html + @../tezos-endorser-$(FLORENCE_SHORT) man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > 009/tezos-endorser-009.html + @../tezos-accuser-$(FLORENCE_SHORT) man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > 009/tezos-accuser-009.html # 008 (Edo) protocol @../tezos-client -protocol $(EDO_LONG) man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > 008/tezos-client-008.html @../tezos-baker-$(EDO_SHORT) man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > 008/tezos-baker-008.html @@ -92,6 +99,7 @@ $(DOCGENDIR)/rpc_doc.exe: rpc: $(DOCGENDIR)/rpc_doc.exe @dune exec $(DOCGENDIR)/rpc_doc.exe "" > 007/rpc.rst @dune exec $(DOCGENDIR)/rpc_doc.exe 008 > 008/rpc.rst + @dune exec $(DOCGENDIR)/rpc_doc.exe 009 > 009/rpc.rst @dune exec $(DOCGENDIR)/rpc_doc.exe alpha > alpha/rpc.rst @dune exec $(DOCGENDIR)/rpc_doc.exe shell > shell/rpc.rst @@ -114,5 +122,5 @@ html: Makefile api/errors.rst rpc p2p clean: @-rm -Rf "$(BUILDDIR)" - @-rm -Rf api/errors.rst 007/rpc.rst 008/rpc.rst shell/rpc.rst shell/p2p_api.rst + @-rm -Rf api/errors.rst 007/rpc.rst 008/rpc.rst 009/rpc.rst shell/rpc.rst shell/p2p_api.rst @-rm -Rf api/tezos-*.html api/tezos-*.txt 007/tezos-*.html 008/tezos-*.html diff --git a/docs/doc_gen/dune b/docs/doc_gen/dune index a981b7a2a39031401966b11e7cbd080841d46efb..fef386e489c1b3974111c4c3a44fbfc639992fc8 100644 --- a/docs/doc_gen/dune +++ b/docs/doc_gen/dune @@ -7,6 +7,7 @@ tezos-protocol-updater tezos-embedded-protocol-007-PsDELPH1 tezos-embedded-protocol-008-PtEdo2Zk + tezos-embedded-protocol-009-PsFLoren tezos-embedded-protocol-alpha re) (flags (:standard -open Tezos_base__TzPervasives diff --git a/docs/doc_gen/rpc_doc.ml b/docs/doc_gen/rpc_doc.ml index 6370abcf3493e318bca05501b6f41a969d47dfa3..f15f9ee5e7742d492ef91d828743c35045e98917 100644 --- a/docs/doc_gen/rpc_doc.ml +++ b/docs/doc_gen/rpc_doc.ml @@ -31,6 +31,10 @@ let protocols = "Alpha", Some "/include/rpc_introduction.rst.inc", "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK" ); + ( "009", + "009 Florence", + Some "/include/rpc_introduction.rst.inc", + "PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i" ); ( "008", "008 Edo", Some "/include/rpc_introduction.rst.inc", diff --git a/docs/index.rst b/docs/index.rst index 027c4804dcdf116ea6a0f2bed9b403971b5f1b82..60be02295f396d5b2f7934853964c465cd3126d7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -146,6 +146,18 @@ in the :ref:`introduction `. 008/cli-commands 008/rpc +.. toctree:: + :maxdepth: 2 + :caption: 009 Florence (No Baking Accounts) doc: + + 009/michelson + 009/proof_of_stake + 009/sapling + 009/voting + 009/glossary + 009/cli-commands + 009/rpc + .. toctree:: :maxdepth: 2 :caption: Alpha Development Protocol doc: @@ -191,6 +203,7 @@ in the :ref:`introduction `. protocols/006_carthage protocols/007_delphi protocols/008_edo + protocols/009_florence protocols/alpha .. toctree:: diff --git a/docs/protocols/009_florence.rst b/docs/protocols/009_florence.rst new file mode 100644 index 0000000000000000000000000000000000000000..cb18441a16a088b6de8e20395f4f7b8114fe04ab --- /dev/null +++ b/docs/protocols/009_florence.rst @@ -0,0 +1,199 @@ +.. _009_florence: + +Protocol 009_PsFLoren Florence +============================== + +This page contains all the relevant information for protocol 009 Florence. + +The code can be found in the ``src/proto_009_PsFLoren`` directory of the +``master`` branch of Tezos and its full hash is +``PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i``. + +This page documents the changes brought by protocol Florence with respect +to Edo. + + +.. contents:: Summary of changes + +Smart Contracts/Michelson +------------------------- + +Increase ``max_operation_data_length`` to 32KB +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The maximal size of operations is doubled. In particular this has the +effect of slightly more than doubling the maximum size of a smart +contract. + +- Commit: + `tezos#3ff6bc8d `__ +- TZIP: + `increase_operation_size_limit `__ + +Fixed a discrepancy between ``CONTRACT`` and ``PACK`` in addresses without entrypoints +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Solves issue: + `tezos#643 `__ +- Commit: + `tezos#e879b1a7 `__ + +Depth-First Execution Order +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The applied order of inter-contract calls emitted by smart contracts has +changed. The operations are now placed in a stack instead of a queue, +resulting in a depth-first as opposed to breadth-first execution order. + +- TZIP: + `tzip!111 `__ +- MR: + `tezos!2420 `__ + +/!\ This is a breaking change that affects the security of smart contracts + +Tooling +------- + +Normalization RPCs +~~~~~~~~~~~~~~~~~~ + +Two new normalization RPCs, ``normalize_data`` and ``normalize_script``, +have been added. They can be used to convert Michelson values and +scripts that have multiple possible representations into a canonical +format. In particular, these RPCs can be used to convert Michelson comb +pairs into the format they had before the introduction of the compact +notations in Edo. + +- Solves issue: + `tezos#1016 `__ +- MR: + `tezos!2354 `__ + +New ``failing_noop`` Operation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A new operation has been added to the protocol that is guaranteed to +fail. This feature can be used by tooling (such as ``tezos-client``) to +sign arbitrary data securely, without fear of malicious injection into +future protocols. + +- Solves issue: + `tezos#52 `__ +- MR: + `tezos!2361 `__ + +Performance +----------- + +Endorsements Now Checked in Linear Time +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Endorsement and double endorsing evidence operations now contain an +additional slot field; the slot should be the smallest among the +endorser's slots. + +Software that make use of operations and receipts will have to be +adapted, in particular indexers. + +Most notably, the first list of operations is now composed of +`endorsement_with_slot` instead of `endorsement` operations. + +The change will not affect custom signing stacks, as the +`endorsement_with_slot` is just an unsigned wrapper around the +Edo-compatible `endorsement` format. + +The reference endorser forges an `endorsement`, sends it to the +signer, and then wraps the result in an `endorsement_with_slot` +before injection. + +- Solves issue: + `tezos#1028 `__ +- MR: + `tezos!2471 `__ + +/!\ Breaking change: the format of endorsements and double endorsing evidences has changed + +Staking balance RPC +~~~~~~~~~~~~~~~~~~~ + +Some users observed degraded performance in v8.1 as reported in issue +`tezos#1067 `__. To +address this, the measurement of staking balance has been reworked, +improving the performance of the +``/chains/[...]/blocks/[...]/context/delegates/[...]`` RPC endpoint. + +- MR: + `tezos!2547 `__ + +Gas Optimizations +~~~~~~~~~~~~~~~~~ + +Various optimizations have been added to the gas accounting subsystem. +Most notably, gas consumption is now computed using `saturated +arithmetic `__. + +- MR’s: + `tezos!2328 `__, + `tezos!2327 `__, + and + `tezos!2329 `__ + +Governance +---------- + +Deactivation of the Test Chain in the Economic Protocol +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Prior to Florence, Tezos nodes spawned a test chain during the “Testing” +phase of voting for the purpose of allowing users to test the new +amendment. However, this feature was both unused in practice and quite +complex. It has been removed, simplifying the amendment protocol. + +Furthermore, the voting periods have been renamed as follows: + 1. Proposal --> Proposal + 2. Testing_vote --> Exploration + 3. Testing --> Cooldown + 4. Promotion_vote --> Promotion + 5. Adoption --> Adoption + +- TZIP: + `tzip!141 `__ +- MR: + `tezos!2469 `__ + +Migration +--------- + +Migrations may now Produce Balance Receipts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Protocol migrations can now update the balance of accounts by producing +balance receipts. This was necessary groundwork for `Baking +Accounts <#Baking-accounts>`__ and facilitates `developer +invoicing `__. + +- Solves issue: + `tezos#138 `__ +- MR: + `tezos!2437 `__ + +Internal +-------- + +Refactoring +~~~~~~~~~~~ + +Abstract protocol types can now be used consistently outside the +protocol. + +- MR: + `tezos!2497 `__ + +Authors & Invoice +----------------- + +This protocol amendment has been developed by Nomadic Labs, Metastate, +Dai Lambda, Ligo, and the following external contributor: +- [Keefer Taylor](https://gitlab.com/keefertaylor), rewarded ꜩ100 for his +contribution on increasing the maximal operation size. diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index 9bb3766a73c38b1d0a82d20b8a91a07f3a1128cb..ca7cd7ff3f8025b0a350e3ddc5ab15e26e94537a 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -9,212 +9,9 @@ development version of the Tezos protocol. The code can be found in the ``src/proto_alpha`` directory of the ``master`` branch of Tezos. -This page documents the changes brought by Protocol Alpha with respect -to Edo. +This page documents the changes brought by protocol Alpha with respect +to Florence. .. contents:: Summary of changes -Baking Accounts ---------------- - -A new account type has been added to represent accounts managed -by bakers. These accounts are Michelson smart contracts running a fixed -multisig script. This feature lets bakers renew and split their -consensus keys without moving to a new address and asking their -delegators to follow. In addition to the usual internal operations, -baking accounts can also emit baking operations such as proposing and -voting for protocol amendments. - -- TZIP: - `tzip!133 `__ -- MR: - `tezos!2458 `__ -- Docs: - `tezos!2490 `__ - -/!\ This is a breaking change, see `the corresponding section in the TZIP. `__ - - -Smart Contracts/Michelson -------------------------- - -Increase ``max_operation_data_length`` to 32KB -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The maximal size of operations is doubled. In particular this has the -effect of slightly more than doubling the maximum size of a smart -contract. - -- Commit: - `tezos#3ff6bc8d `__ -- TZIP: - `increase_operation_size_limit `__ - -Fixed a discrepancy between ``CONTRACT`` and ``PACK`` in addresses without entrypoints -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Solves issue: - `tezos#643 `__ -- Commit: - `tezos#e879b1a7 `__ - -Depth-First Execution Order -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The applied order of inter-contract calls emitted by smart contracts has -changed. The operations are now placed in a stack instead of a queue, -resulting in a depth-first as opposed to breadth-first execution order. - -- TZIP: - `tzip!111 `__ -- MR: - `tezos!2420 `__ - -/!\ This is a breaking change that affects the security of smart contracts - -Tooling -------- - -Normalization RPCs -~~~~~~~~~~~~~~~~~~ - -Two new normalization RPCs, ``normalize_data`` and ``normalize_script``, -have been added. They can be used to convert Michelson values and -scripts that have multiple possible representations into a canonical -format. In particular, these RPCs can be used to convert Michelson comb -pairs into the format they had before the introduction of the compact -notations in Edo. - -- Solves issue: - `tezos#1016 `__ -- MR: - `tezos!2354 `__ - -New ``failing_noop`` Operation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A new operation has been added to the protocol that is guaranteed to -fail. This feature can be used by tooling (such as ``tezos-client``) to -sign arbitrary data securely, without fear of malicious injection into -future protocols. - -- Solves issue: - `tezos#52 `__ -- MR: - `tezos!2361 `__ - -Performance ------------ - -Endorsements Now Checked in Linear Time -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Endorsement and double endorsing evidence operations now contain an -additional slot field; the slot should be the smallest among the -endorser's slots. - -Software that make use of operations and receipts will have to be -adapted, in particular indexers. - -Most notably, the first list of operations is now composed of -`endorsement_with_slot` instead of `endorsement` operations. - -The change will not affect custom signing stacks, as the -`endorsement_with_slot` is just an unsigned wrapper around the -Edo-compatible `endorsement` format. - -The reference endorser forges an `endorsement`, sends it to the -signer, and then wraps the result in an `endorsement_with_slot` -before injection. - -- Solves issue: - `tezos#1028 `__ -- MR: - `tezos!2471 `__ - -/!\ Breaking change: the format of endorsements and double endorsing evidences has changed - -Staking balance RPC -~~~~~~~~~~~~~~~~~~~ - -Some users observed degraded performance in v8.1 as reported in issue -`tezos#1067 `__. To -address this, the measurement of staking balance has been reworked, -improving the performance of the -``/chains/[...]/blocks/[...]/context/delegates/[...]`` RPC endpoint. - -- MR: - `tezos!2547 `__ - -Gas Optimizations -~~~~~~~~~~~~~~~~~ - -Various optimizations have been added to the gas accounting subsystem. -Most notably, gas consumption is now computed using `saturated -arithmetic `__. - -- MR’s: - `tezos!2328 `__, - `tezos!2327 `__, - and - `tezos!2329 `__ - -Governance ----------- - -Deactivation of the Test Chain in the Economic Protocol -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Prior to Florence, Tezos nodes spawned a test chain during the “Testing” -phase of voting for the purpose of allowing users to test the new -amendment. However, this feature was both unused in practice and quite -complex. It has been removed, simplifying the amendment protocol. - -Furthermore, the voting periods have been renamed as follows: - 1. Proposal --> Proposal - 2. Testing_vote --> Exploration - 3. Testing --> Cooldown - 4. Promotion_vote --> Promotion - 5. Adoption --> Adoption - -- TZIP: - `tzip!141 `__ -- MR: - `tezos!2469 `__ - -Migration ---------- - -Migrations may now Produce Balance Receipts -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Protocol migrations can now update the balance of accounts by producing -balance receipts. This was necessary groundwork for `Baking -Accounts <#Baking-accounts>`__ and facilitates `developer -invoicing `__. - -- Solves issue: - `tezos#138 `__ -- MR: - `tezos!2437 `__ - -Internal --------- - -Refactoring -~~~~~~~~~~~ - -Abstract protocol types can now be used consistently outside the -protocol. - -- MR: - `tezos!2497 `__ - -Authors & Invoice ------------------ - -This protocol amendment has been developed by Nomadic Labs, Metastate, -Dai Lambda, Ligo, and the following external contributor: -- [Keefer Taylor](https://gitlab.com/keefertaylor), rewarded ꜩ100 for his -contribution on increasing the maximal operation size. diff --git a/src/bin_client/dune b/src/bin_client/dune index 9b4f7c1a26e2c0861f3719b31a489de2c590a077..f5b544e57cafa07f8faa3a2d8494b1357182807e 100644 --- a/src/bin_client/dune +++ b/src/bin_client/dune @@ -48,6 +48,9 @@ (select void_for_linking-008-PtEdo2Zk from (tezos-client-008-PtEdo2Zk-commands-registration -> void_for_linking-008-PtEdo2Zk.empty) (-> void_for_linking-008-PtEdo2Zk.empty)) + (select void_for_linking-009-PsFLoren from + (tezos-client-009-PsFLoren-commands-registration -> void_for_linking-009-PsFLoren.empty) + (-> void_for_linking-009-PsFLoren.empty)) (select void_for_linking-alpha from (tezos-client-alpha-commands-registration -> void_for_linking-alpha.empty) @@ -65,6 +68,9 @@ (select void_for_linking-baking-008-PtEdo2Zk from (tezos-baking-008-PtEdo2Zk-commands.registration -> void_for_linking-baking-008-PtEdo2Zk.empty) (-> void_for_linking-baking-008-PtEdo2Zk.empty)) + (select void_for_linking-baking-009-PsFLoren from + (tezos-baking-009-PsFLoren-commands.registration -> void_for_linking-baking-009-PsFLoren.empty) + (-> void_for_linking-baking-009-PsFLoren.empty)) tezos-stdlib-unix tezos-client-base-unix tezos-signer-backends.unix) @@ -93,11 +99,13 @@ (write-file void_for_linking-006-PsCARTHA.empty "") (write-file void_for_linking-007-PsDELPH1.empty "") (write-file void_for_linking-008-PtEdo2Zk.empty "") + (write-file void_for_linking-009-PsFLoren.empty "") (write-file void_for_linking-alpha.empty "") (write-file void_for_linking-demo-counter.empty "") (write-file void_for_linking-baking-alpha.empty "") (write-file void_for_linking-baking-007-PsDELPH1.empty "") (write-file void_for_linking-baking-008-PtEdo2Zk.empty "") + (write-file void_for_linking-baking-009-PsFLoren.empty "") ))) (install diff --git a/src/bin_client/tezos-client.opam b/src/bin_client/tezos-client.opam index fb6f3ab0e4e937d5dccfea48743ff6d6cfccab0c..34662dffa2d61e60e0093776bb1f389eb41b328d 100644 --- a/src/bin_client/tezos-client.opam +++ b/src/bin_client/tezos-client.opam @@ -24,6 +24,7 @@ depends: [ "tezos-client-006-PsCARTHA" "tezos-client-007-PsDELPH1" "tezos-client-008-PtEdo2Zk" + "tezos-client-009-PsFLoren" "tezos-client-demo-counter" "tezos-client-alpha-commands" @@ -35,10 +36,12 @@ depends: [ "tezos-client-006-PsCARTHA-commands" "tezos-client-007-PsDELPH1-commands-registration" "tezos-client-008-PtEdo2Zk-commands-registration" + "tezos-client-009-PsFLoren-commands-registration" "tezos-baking-alpha-commands" "tezos-baking-007-PsDELPH1-commands" "tezos-baking-008-PtEdo2Zk-commands" + "tezos-baking-009-PsFLoren-commands" "tezos-client-base-unix" "tezos-mockup-commands" diff --git a/src/bin_codec/dune b/src/bin_codec/dune index e7939569a7ed9d6170614880981ab99f61803221..4cd2364a61d7b4e35b99ab29ca98028b2210fe9a 100644 --- a/src/bin_codec/dune +++ b/src/bin_codec/dune @@ -25,6 +25,9 @@ (select void_for_linking-008-PtEdo2Zk from (tezos-client-008-PtEdo2Zk -> void_for_linking-008-PtEdo2Zk.empty) (-> void_for_linking-008-PtEdo2Zk.empty)) + (select void_for_linking-009-PsFLoren from + (tezos-client-009-PsFLoren -> void_for_linking-009-PsFLoren.empty) + (-> void_for_linking-009-PsFLoren.empty)) ) (flags (:standard -open Data_encoding -open Tezos_base__TzPervasives @@ -43,6 +46,7 @@ (write-file void_for_linking-006-PsCARTHA.empty "") (write-file void_for_linking-007-PsDELPH1.empty "") (write-file void_for_linking-008-PtEdo2Zk.empty "") + (write-file void_for_linking-009-PsFLoren.empty "") ))) (rule diff --git a/src/bin_codec/tezos-codec.opam b/src/bin_codec/tezos-codec.opam index e75f6b9624c4c6a371589c53f982165ab0b3a967..a64debd203bd3d905bca2d616503f05000fff3a0 100644 --- a/src/bin_codec/tezos-codec.opam +++ b/src/bin_codec/tezos-codec.opam @@ -23,6 +23,7 @@ depopts: [ "tezos-client-006-PsCARTHA" "tezos-client-007-PsDELPH1" "tezos-client-008-PtEdo2Zk" + "tezos-client-009-PsFLoren" ] build: [ ["dune" "build" "-p" name "-j" jobs] diff --git a/src/bin_node/dune b/src/bin_node/dune index a30b0a794fca7c3d4ae862d8ba9d24427e137888..16ee06a54c5f0d0c5deeafe1eebd9433c253890b 100644 --- a/src/bin_node/dune +++ b/src/bin_node/dune @@ -77,6 +77,9 @@ (select void_for_linking-008-PtEdo2Zk-protocol-plugin-registerer from (tezos-protocol-plugin-008-PtEdo2Zk-registerer -> void_for_linking-008-PtEdo2Zk-protocol-plugin-registerer.empty) (-> void_for_linking-008-PtEdo2Zk-protocol-plugin-registerer.empty)) + (select void_for_linking-009-PsFLoren-protocol-plugin-registerer from + (tezos-protocol-plugin-009-PsFLoren-registerer -> void_for_linking-009-PsFLoren-protocol-plugin-registerer.empty) + (-> void_for_linking-009-PsFLoren-protocol-plugin-registerer.empty)) (select void_for_linking-alpha-protocol-plugin-registerer from (tezos-protocol-plugin-alpha-registerer -> void_for_linking-alpha-protocol-plugin-registerer.empty) (-> void_for_linking-alpha-protocol-plugin-registerer.empty)) @@ -117,9 +120,11 @@ (write-file void_for_linking-007-PsDELPH1.empty "") (write-file void_for_linking-008-PtEdoTez.empty "") (write-file void_for_linking-008-PtEdo2Zk.empty "") + (write-file void_for_linking-009-PsFLoren.empty "") (write-file void_for_linking-alpha-protocol-plugin-registerer.empty "") (write-file void_for_linking-007-PsDELPH1-protocol-plugin-registerer.empty "") (write-file void_for_linking-008-PtEdo2Zk-protocol-plugin-registerer.empty "") + (write-file void_for_linking-009-PsFLoren-protocol-plugin-registerer.empty "") ))) (install diff --git a/src/bin_node/tezos-node.opam b/src/bin_node/tezos-node.opam index 0c576f20949cbafbab9bf64b2fb1e566f305b38a..8fe6604db3ef353677dd7e312583cb9e6a51741e 100644 --- a/src/bin_node/tezos-node.opam +++ b/src/bin_node/tezos-node.opam @@ -32,8 +32,10 @@ depends: [ "tezos-embedded-protocol-006-PsCARTHA" "tezos-embedded-protocol-007-PsDELPH1" "tezos-embedded-protocol-008-PtEdo2Zk" + "tezos-embedded-protocol-009-PsFLoren" "tezos-protocol-plugin-007-PsDELPH1-registerer" "tezos-protocol-plugin-008-PtEdo2Zk-registerer" + "tezos-protocol-plugin-009-PsFLoren-registerer" "tezos-protocol-plugin-alpha-registerer" "cmdliner" "lwt-exit" diff --git a/src/bin_sandbox/command_ledger_wallet.ml b/src/bin_sandbox/command_ledger_wallet.ml index c140074883ffa0f07f9ff8f51954dc9c3a4f38ee..745fb0817411807c1506e53a98a99b3141b96dfc 100644 --- a/src/bin_sandbox/command_ledger_wallet.ml +++ b/src/bin_sandbox/command_ledger_wallet.ml @@ -225,7 +225,7 @@ let voting_tests state ~client ~src ~with_rejections ~protocol_kind match protocol_kind with | `Athens -> () - | `Babylon | `Carthage | `Delphi | `Edo | `Alpha -> + | `Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha -> wf ppf "From Babylon on, You will first be asked to provide the \ @@ -275,7 +275,7 @@ let voting_tests state ~client ~src ~with_rejections ~protocol_kind match protocol_kind with | `Athens -> () - | `Babylon | `Carthage | `Delphi | `Edo | `Alpha -> + | `Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha -> wf ppf "On Alpha, Babylon and Carthage, You will first be \ @@ -364,7 +364,7 @@ let originate_manager_tz_script state ~client ~name ~from ~bake ~protocol_kind @ ( match protocol_kind with | `Athens -> ["for"; from] - | `Babylon | `Carthage | `Delphi | `Edo | `Alpha -> + | `Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha -> [] ) @ [ "transferring"; "350"; @@ -737,7 +737,7 @@ let delegation_tests state ~client ~src ~with_rejections ~protocol_kind match protocol_kind with | `Athens -> self_delegation () - | `Babylon | `Carthage | `Delphi | `Edo | `Alpha -> + | `Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha -> tz_account_delegation () >>= fun () -> self_delegation () let transaction_tests state ~client ~src ~with_rejections ~protocol_kind @@ -915,7 +915,7 @@ let prepare_origination_of_id_script ?(spendable = false) @ ( match protocol_kind with | `Athens -> ["for"; from] - | `Babylon | `Carthage | `Delphi | `Edo | `Alpha -> + | `Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha -> [] ) @ [ "transferring"; amount; @@ -1067,7 +1067,7 @@ let basic_contract_operations_tests state ~client ~src ~with_rejections ~init_storage:"\"delegatable contract\"" ~delegatable:true () - | `Babylon | `Carthage | `Delphi | `Edo | `Alpha -> + | `Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha -> return () ) >>= fun () -> let push_drops = diff --git a/src/bin_sandbox/dune b/src/bin_sandbox/dune index d393a72db6eb4f9865abaeaf3b03b9c86b392610..1a60e06f9088f24f971af93563f2506af58092aa 100644 --- a/src/bin_sandbox/dune +++ b/src/bin_sandbox/dune @@ -69,6 +69,30 @@ --hard-fork-accuser %{bin:tezos-accuser-008-PtEdo2Zk} ))) +(rule + (alias runtest_sandbox_user_activated_upgrade_next) + (locks /tcp-port/40000_range) + (action + (run %{exe:main.exe} mini-net + --root-path %{env:ROOT_PATH=/tmp/flextesa-hard-fork/} + --base-port 40_000 + --size 2 + --number-of-b 2 + --with-timestamp + --until 20 + --protocol-hash PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA + --protocol-kind Edo + --tezos-client %{bin:tezos-client} + --tezos-node %{bin:tezos-node} + --tezos-baker %{bin:tezos-baker-008-PtEdo2Zk} + --tezos-endorser %{bin:tezos-endorser-008-PtEdo2Zk} + --tezos-accuser %{bin:tezos-accuser-008-PtEdo2Zk} + --hard-fork 10:PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i + --hard-fork-baker %{bin:tezos-baker-009-PsFLoren} + --hard-fork-endorser %{bin:tezos-endorser-009-PsFLoren} + --hard-fork-accuser %{bin:tezos-accuser-009-PsFLoren} + ))) + (rule (alias runtest_sandbox_user_activated_upgrade_alpha) (locks /tcp-port/40000_range) @@ -121,6 +145,34 @@ --second-accuser %{bin:tezos-accuser-008-PtEdo2Zk} ))) +(rule + (alias runtest_sandbox_daemons_upgrade_next) + (locks /tcp-port/50000_range) + (action + (run %{exe:main.exe} daemons-upgrade + %{lib:tezos-protocol-009-PsFLoren:raw/TEZOS_PROTOCOL} + --root-path %{env:ROOT_PATH=/tmp/flextesa-daemons-upgrade/} + --base-port 50_000 + --extra-dummy-proposals-batch-size 2 + --extra-dummy-proposals-batch-levels 3,5 + --size 2 + --number-of-b 2 + --time-betw 3 + --blocks-per-vot 14 + --with-timestamp + --protocol-hash PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA + --protocol-kind Edo + --tezos-client %{bin:tezos-client} + --tezos-admin %{bin:tezos-admin-client} + --tezos-node %{bin:tezos-node} + --first-baker %{bin:tezos-baker-008-PtEdo2Zk} + --first-endorser %{bin:tezos-endorser-008-PtEdo2Zk} + --first-accuser %{bin:tezos-accuser-008-PtEdo2Zk} + --second-baker %{bin:tezos-baker-009-PsFLoren} + --second-endorser %{bin:tezos-endorser-009-PsFLoren} + --second-accuser %{bin:tezos-accuser-009-PsFLoren} + ))) + (rule (alias runtest_sandbox_daemons_upgrade_alpha) (locks /tcp-port/50000_range) @@ -228,8 +280,10 @@ (alias runtest_sandbox_accusations_simple_double_endorsing) (alias runtest_sandbox_voting_demo_noops) (alias runtest_sandbox_user_activated_upgrade_active) + (alias runtest_sandbox_user_activated_upgrade_next) (alias runtest_sandbox_user_activated_upgrade_alpha) (alias runtest_sandbox_daemons_upgrade_active) + (alias runtest_sandbox_daemons_upgrade_next) (alias runtest_sandbox_daemons_upgrade_alpha) (alias runtest_sandbox_node_synchronization)) (action (progn))) diff --git a/src/lib_protocol_compiler/final_protocol_versions b/src/lib_protocol_compiler/final_protocol_versions index b7c5b6b9157cd13d8187e74d8514e16cc9f084a3..8153f7b43559fe4f58ab6af792b4c3d282c6eb6c 100644 --- a/src/lib_protocol_compiler/final_protocol_versions +++ b/src/lib_protocol_compiler/final_protocol_versions @@ -8,4 +8,5 @@ PsBabyM1eUXZseaJdmXFApDSBqj8YBfwELoxZHHW77EMcAbbwAS PsCARTHAGazKbHtnKfLzQg3kms52kSRpgnDY982a9oYsSXRLQEb PsDELPH1Kxsxt8f9eWbxQeRxkjfbxoqM52jvs5Y5fBxWWh4ifpo PtEdoTezd3RHSC31mpxxo1npxFjoWWcFgQtxapi51Z8TLu6v6Uq -PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA \ No newline at end of file +PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA +PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i \ No newline at end of file diff --git a/src/proto_009_PsFLoren/bin_accuser/.ocamlformat b/src/proto_009_PsFLoren/bin_accuser/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/bin_accuser/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/bin_accuser/dune b/src/proto_009_PsFLoren/bin_accuser/dune new file mode 100644 index 0000000000000000000000000000000000000000..11c77973e38e4e95570b1e0f30941fa149156373 --- /dev/null +++ b/src/proto_009_PsFLoren/bin_accuser/dune @@ -0,0 +1,18 @@ +(executable + (name main_accuser_009_PsFLoren) + (public_name tezos-accuser-009-PsFLoren) + (libraries tezos-client-base-unix + tezos-client-commands + tezos-baking-009-PsFLoren-commands) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren + -open Tezos_client_009_PsFLoren + -open Tezos_client_commands + -open Tezos_baking_009_PsFLoren_commands + -open Tezos_stdlib_unix + -open Tezos_client_base_unix))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/bin_accuser/dune-project b/src/proto_009_PsFLoren/bin_accuser/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..464a475c1cc92d3577fe6e7369f7cee4b41ca4c0 --- /dev/null +++ b/src/proto_009_PsFLoren/bin_accuser/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-accuser-alpha) diff --git a/src/proto_009_PsFLoren/bin_accuser/main_accuser_009_PsFLoren.ml b/src/proto_009_PsFLoren/bin_accuser/main_accuser_009_PsFLoren.ml new file mode 100644 index 0000000000000000000000000000000000000000..251452cd30219f49c2ca89a40064e4db0614bf00 --- /dev/null +++ b/src/proto_009_PsFLoren/bin_accuser/main_accuser_009_PsFLoren.ml @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = + Client_commands.register Protocol.hash + @@ fun _network -> + List.map (Clic.map_command (new Protocol_client_context.wrap_full)) + @@ Delegate_commands.accuser_commands () + +let select_commands _ _ = + return + (List.map + (Clic.map_command (new Protocol_client_context.wrap_full)) + (Delegate_commands.accuser_commands ())) + +let () = Client_main_run.run (module Client_config) ~select_commands diff --git a/src/proto_009_PsFLoren/bin_accuser/tezos-accuser-009-PsFLoren.opam b/src/proto_009_PsFLoren/bin_accuser/tezos-accuser-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..89ba86f9a02860345a9b54b8d22481675933ec4a --- /dev/null +++ b/src/proto_009_PsFLoren/bin_accuser/tezos-accuser-009-PsFLoren.opam @@ -0,0 +1,21 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-client-009-PsFLoren" + "tezos-client-commands" + "tezos-baking-009-PsFLoren-commands" + "tezos-client-base-unix" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: accuser binary" diff --git a/src/proto_009_PsFLoren/bin_baker/.ocamlformat b/src/proto_009_PsFLoren/bin_baker/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/bin_baker/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/bin_baker/dune b/src/proto_009_PsFLoren/bin_baker/dune new file mode 100644 index 0000000000000000000000000000000000000000..0535edf13cfc13e9648b8b81fc833dc437c38526 --- /dev/null +++ b/src/proto_009_PsFLoren/bin_baker/dune @@ -0,0 +1,18 @@ +(executable + (name main_baker_009_PsFLoren) + (public_name tezos-baker-009-PsFLoren) + (libraries tezos-client-base-unix + tezos-client-commands + tezos-baking-009-PsFLoren-commands) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren + -open Tezos_client_009_PsFLoren + -open Tezos_client_commands + -open Tezos_baking_009_PsFLoren_commands + -open Tezos_stdlib_unix + -open Tezos_client_base_unix))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/bin_baker/dune-project b/src/proto_009_PsFLoren/bin_baker/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..fd1816c8e0caea189beeab5bb6ab321a6db32c70 --- /dev/null +++ b/src/proto_009_PsFLoren/bin_baker/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-baker-alpha) diff --git a/src/proto_009_PsFLoren/bin_baker/main_baker_009_PsFLoren.ml b/src/proto_009_PsFLoren/bin_baker/main_baker_009_PsFLoren.ml new file mode 100644 index 0000000000000000000000000000000000000000..70ca757db00846016ba67267444d5e372e374b33 --- /dev/null +++ b/src/proto_009_PsFLoren/bin_baker/main_baker_009_PsFLoren.ml @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = + Client_commands.register Protocol.hash + @@ fun _network -> + List.map (Clic.map_command (new Protocol_client_context.wrap_full)) + @@ Delegate_commands.delegate_commands () + +let select_commands _ _ = + return + (List.map + (Clic.map_command (new Protocol_client_context.wrap_full)) + (Delegate_commands.baker_commands ())) + +(* This call is not strictly necessary as the parameters are initialized + lazily the first time a Sapling operation (validation or forging) is + done. This is what the client does. + For a long running binary however it is important to make sure that the + parameters files are there at the start and avoid failing much later while + validating an operation. Plus paying this cost upfront means that the first + validation will not be more expensive. *) +let () = Tezos_sapling.Core.Validator.init_params () + +let () = Client_main_run.run (module Client_config) ~select_commands diff --git a/src/proto_009_PsFLoren/bin_baker/tezos-baker-009-PsFLoren.opam b/src/proto_009_PsFLoren/bin_baker/tezos-baker-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..21120351f40b2ac7b8249e54f64d6c410d098ca5 --- /dev/null +++ b/src/proto_009_PsFLoren/bin_baker/tezos-baker-009-PsFLoren.opam @@ -0,0 +1,21 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-client-009-PsFLoren" + "tezos-client-commands" + "tezos-baking-009-PsFLoren-commands" + "tezos-client-base-unix" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: baker binary" diff --git a/src/proto_009_PsFLoren/bin_endorser/.ocamlformat b/src/proto_009_PsFLoren/bin_endorser/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/bin_endorser/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/bin_endorser/dune b/src/proto_009_PsFLoren/bin_endorser/dune new file mode 100644 index 0000000000000000000000000000000000000000..c19a310a8fec35ba39f7f4bf9a8d2ded79b76950 --- /dev/null +++ b/src/proto_009_PsFLoren/bin_endorser/dune @@ -0,0 +1,18 @@ +(executable + (name main_endorser_009_PsFLoren) + (public_name tezos-endorser-009-PsFLoren) + (libraries tezos-client-base-unix + tezos-client-commands + tezos-baking-009-PsFLoren-commands) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren + -open Tezos_client_009_PsFLoren + -open Tezos_client_commands + -open Tezos_baking_009_PsFLoren_commands + -open Tezos_stdlib_unix + -open Tezos_client_base_unix))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/bin_endorser/dune-project b/src/proto_009_PsFLoren/bin_endorser/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..036de336a7f0b82991c8c2b3bfcc5243d2bcca91 --- /dev/null +++ b/src/proto_009_PsFLoren/bin_endorser/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-endorser-alpha) diff --git a/src/proto_009_PsFLoren/bin_endorser/main_endorser_009_PsFLoren.ml b/src/proto_009_PsFLoren/bin_endorser/main_endorser_009_PsFLoren.ml new file mode 100644 index 0000000000000000000000000000000000000000..28ee588dc72e99c06aec913b7773b0cedff947ed --- /dev/null +++ b/src/proto_009_PsFLoren/bin_endorser/main_endorser_009_PsFLoren.ml @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = + Client_commands.register Protocol.hash + @@ fun _network -> + List.map (Clic.map_command (new Protocol_client_context.wrap_full)) + @@ Delegate_commands.delegate_commands () + +let select_commands _ _ = + return + (List.map + (Clic.map_command (new Protocol_client_context.wrap_full)) + (Delegate_commands.endorser_commands ())) + +let () = Client_main_run.run (module Client_config) ~select_commands diff --git a/src/proto_009_PsFLoren/bin_endorser/tezos-endorser-009-PsFLoren.opam b/src/proto_009_PsFLoren/bin_endorser/tezos-endorser-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..f0ee84835fc762e2f5b8e3973879d4d71710d12f --- /dev/null +++ b/src/proto_009_PsFLoren/bin_endorser/tezos-endorser-009-PsFLoren.opam @@ -0,0 +1,21 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-client-009-PsFLoren" + "tezos-client-commands" + "tezos-baking-009-PsFLoren-commands" + "tezos-client-base-unix" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: endorser binary" diff --git a/src/proto_009_PsFLoren/lib_client/.ocamlformat b/src/proto_009_PsFLoren/lib_client/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_args.ml b/src/proto_009_PsFLoren/lib_client/client_proto_args.ml new file mode 100644 index 0000000000000000000000000000000000000000..cb7d9001259849fdd68d828b14792cb3120dd13a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_args.ml @@ -0,0 +1,523 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Protocol +open Alpha_context +open Clic + +type error += Bad_tez_arg of string * string (* Arg_name * value *) + +type error += Bad_max_priority of string + +type error += Bad_minimal_fees of string + +type error += Bad_max_waiting_time of string + +type error += Bad_endorsement_delay of string + +type error += Bad_preserved_levels of string + +let () = + register_error_kind + `Permanent + ~id:"badTezArg" + ~title:"Bad Tez Arg" + ~description:"Invalid \xEA\x9C\xA9 notation in parameter." + ~pp:(fun ppf (arg_name, literal) -> + Format.fprintf + ppf + "Invalid \xEA\x9C\xA9 notation in parameter %s: '%s'" + arg_name + literal) + Data_encoding.(obj2 (req "parameter" string) (req "literal" string)) + (function + | Bad_tez_arg (parameter, literal) -> + Some (parameter, literal) + | _ -> + None) + (fun (parameter, literal) -> Bad_tez_arg (parameter, literal)) ; + register_error_kind + `Permanent + ~id:"badMaxPriorityArg" + ~title:"Bad -max-priority arg" + ~description:"invalid priority in -max-priority" + ~pp:(fun ppf literal -> + Format.fprintf ppf "invalid priority '%s' in -max-priority" literal) + Data_encoding.(obj1 (req "parameter" string)) + (function Bad_max_priority parameter -> Some parameter | _ -> None) + (fun parameter -> Bad_max_priority parameter) ; + register_error_kind + `Permanent + ~id:"badMinimalFeesArg" + ~title:"Bad -minimal-fees arg" + ~description:"invalid fee threshold in -fee-threshold" + ~pp:(fun ppf literal -> + Format.fprintf ppf "invalid minimal fees '%s'" literal) + Data_encoding.(obj1 (req "parameter" string)) + (function Bad_minimal_fees parameter -> Some parameter | _ -> None) + (fun parameter -> Bad_minimal_fees parameter) ; + register_error_kind + `Permanent + ~id:"badMaxWaitingTimeArg" + ~title:"Bad -max-waiting-time arg" + ~description:"invalid duration in -max-waiting-time" + ~pp:(fun ppf literal -> + Format.fprintf + ppf + "Bad argument value for -max-waiting-time. Expected an integer, but \ + given '%s'" + literal) + Data_encoding.(obj1 (req "parameter" string)) + (function Bad_max_waiting_time parameter -> Some parameter | _ -> None) + (fun parameter -> Bad_max_waiting_time parameter) ; + register_error_kind + `Permanent + ~id:"badEndorsementDelayArg" + ~title:"Bad -endorsement-delay arg" + ~description:"invalid duration in -endorsement-delay" + ~pp:(fun ppf literal -> + Format.fprintf + ppf + "Bad argument value for -endorsement-delay. Expected an integer, but \ + given '%s'" + literal) + Data_encoding.(obj1 (req "parameter" string)) + (function Bad_endorsement_delay parameter -> Some parameter | _ -> None) + (fun parameter -> Bad_endorsement_delay parameter) ; + register_error_kind + `Permanent + ~id:"badPreservedLevelsArg" + ~title:"Bad -preserved-levels arg" + ~description:"invalid number of levels in -preserved-levels" + ~pp:(fun ppf literal -> + Format.fprintf + ppf + "Bad argument value for -preserved_levels. Expected a positive \ + integer, but given '%s'" + literal) + Data_encoding.(obj1 (req "parameter" string)) + (function Bad_preserved_levels parameter -> Some parameter | _ -> None) + (fun parameter -> Bad_preserved_levels parameter) + +let tez_sym = "\xEA\x9C\xA9" + +let string_parameter = parameter (fun _ x -> return x) + +let int_parameter = + parameter (fun _ p -> + try return (int_of_string p) with _ -> failwith "Cannot read int") + +let bytes_of_prefixed_string s = + try + if String.length s < 2 || s.[0] <> '0' || s.[1] <> 'x' then raise Exit + else return (Hex.to_bytes (`Hex (String.sub s 2 (String.length s - 2)))) + with _ -> + failwith "Invalid bytes, expecting hexadecimal notation (e.g. 0x1234abcd)" + +let bytes_parameter = parameter (fun _ s -> bytes_of_prefixed_string s) + +let init_arg = + default_arg + ~long:"init" + ~placeholder:"data" + ~doc:"initial value of the contract's storage" + ~default:"Unit" + string_parameter + +let arg_arg = + arg + ~long:"arg" + ~placeholder:"data" + ~doc:"argument passed to the contract's script, if needed" + string_parameter + +let default_arg_arg = + arg + ~long:"default-arg" + ~placeholder:"data" + ~doc:"default argument passed to each contract's script, if needed" + string_parameter + +let delegate_arg = + Client_keys.Public_key_hash.source_arg + ~long:"delegate" + ~placeholder:"address" + ~doc:"delegate of the contract\nMust be a known address." + () + +let source_arg = + arg + ~long:"source" + ~placeholder:"address" + ~doc:"source of the deposits to be paid\nMust be a known address." + string_parameter + +let entrypoint_arg = + arg + ~long:"entrypoint" + ~placeholder:"name" + ~doc:"entrypoint of the smart contract" + string_parameter + +let default_entrypoint_arg = + arg + ~long:"default-entrypoint" + ~placeholder:"name" + ~doc:"default entrypoint of the smart contracts" + string_parameter + +let force_switch = + switch + ~long:"force" + ~short:'f' + ~doc: + "disables the node's injection checks\n\ + Force the injection of branch-invalid operation or force the \ + injection of block without a fitness greater than the current head." + () + +let minimal_timestamp_switch = + switch + ~long:"minimal-timestamp" + ~doc: + "Use the minimal timestamp instead of the current date as timestamp of \ + the baked block." + () + +let tez_format = + "Text format: `DDDDDDD.DDDDDD`.\n\ + Tez and mutez and separated by a period sign. Trailing and pending zeroes \ + are allowed." + +let tez_parameter param = + parameter (fun _ s -> + match Tez.of_string s with + | Some tez -> + return tez + | None -> + fail (Bad_tez_arg (param, s))) + +let tez_arg ~default ~parameter ~doc = + default_arg + ~long:parameter + ~placeholder:"amount" + ~doc + ~default + (tez_parameter ("--" ^ parameter)) + +let tez_param ~name ~desc next = + Clic.param + ~name + ~desc:(desc ^ " in \xEA\x9C\xA9\n" ^ tez_format) + (tez_parameter name) + next + +let fee_arg = + arg + ~long:"fee" + ~placeholder:"amount" + ~doc:"fee in \xEA\x9C\xA9 to pay to the baker" + (tez_parameter "--fee") + +let default_fee_arg = + arg + ~long:"default-fee" + ~placeholder:"amount" + ~doc:"default fee in \xEA\x9C\xA9 to pay to the baker for each transaction" + (tez_parameter "--default-fee") + +let gas_limit_kind = + parameter (fun _ s -> + try + let v = Z.of_string s in + return (Gas.Arith.integral_exn v) + with _ -> failwith "invalid gas limit (must be a positive number)") + +let gas_limit_arg = + arg + ~long:"gas-limit" + ~short:'G' + ~placeholder:"amount" + ~doc: + "Set the gas limit of the transaction instead of letting the client \ + decide based on a simulation" + gas_limit_kind + +let default_gas_limit_arg = + arg + ~long:"default-gas-limit" + ~short:'G' + ~placeholder:"amount" + ~doc: + "Set the default gas limit for each transaction instead of letting the \ + client decide based on a simulation" + gas_limit_kind + +let storage_limit_kind = + parameter (fun _ s -> + try + let v = Z.of_string s in + assert (Compare.Z.(v >= Z.zero)) ; + return v + with _ -> + failwith "invalid storage limit (must be a positive number of bytes)") + +let storage_limit_arg = + arg + ~long:"storage-limit" + ~short:'S' + ~placeholder:"amount" + ~doc: + "Set the storage limit of the transaction instead of letting the client \ + decide based on a simulation" + storage_limit_kind + +let default_storage_limit_arg = + arg + ~long:"default-storage-limit" + ~short:'S' + ~placeholder:"amount" + ~doc: + "Set the default storage limit for each transaction instead of letting \ + the client decide based on a simulation" + storage_limit_kind + +let counter_arg = + arg + ~long:"counter" + ~short:'C' + ~placeholder:"counter" + ~doc:"Set the counter to be used by the transaction" + (parameter (fun _ s -> + try + let v = Z.of_string s in + assert (Compare.Z.(v >= Z.zero)) ; + return v + with _ -> + failwith "invalid counter (must be a positive number of bytes)")) + +let max_priority_arg = + arg + ~long:"max-priority" + ~placeholder:"slot" + ~doc:"maximum allowed baking slot" + (parameter (fun _ s -> + try return (int_of_string s) with _ -> fail (Bad_max_priority s))) + +let default_minimal_fees = + match Tez.of_mutez 100L with None -> assert false | Some t -> t + +let default_minimal_nanotez_per_gas_unit = Q.of_int 100 + +let default_minimal_nanotez_per_byte = Q.of_int 1000 + +let minimal_fees_arg = + default_arg + ~long:"minimal-fees" + ~placeholder:"amount" + ~doc:"exclude operations with fees lower than this threshold (in tez)" + ~default:(Tez.to_string default_minimal_fees) + (parameter (fun _ s -> + match Tez.of_string s with + | Some t -> + return t + | None -> + fail (Bad_minimal_fees s))) + +let minimal_nanotez_per_gas_unit_arg = + default_arg + ~long:"minimal-nanotez-per-gas-unit" + ~placeholder:"amount" + ~doc: + "exclude operations with fees per gas lower than this threshold (in \ + nanotez)" + ~default:(Q.to_string default_minimal_nanotez_per_gas_unit) + (parameter (fun _ s -> + try return (Q.of_string s) with _ -> fail (Bad_minimal_fees s))) + +let minimal_nanotez_per_byte_arg = + default_arg + ~long:"minimal-nanotez-per-byte" + ~placeholder:"amount" + ~default:(Q.to_string default_minimal_nanotez_per_byte) + ~doc: + "exclude operations with fees per byte lower than this threshold (in \ + nanotez)" + (parameter (fun _ s -> + try return (Q.of_string s) with _ -> fail (Bad_minimal_fees s))) + +let force_low_fee_arg = + switch + ~long:"force-low-fee" + ~doc:"Don't check that the fee is lower than the estimated default value" + () + +let fee_cap_arg = + default_arg + ~long:"fee-cap" + ~placeholder:"amount" + ~default:"1.0" + ~doc:"Set the fee cap" + (parameter (fun _ s -> + match Tez.of_string s with + | Some t -> + return t + | None -> + failwith "Bad fee cap")) + +let burn_cap_arg = + default_arg + ~long:"burn-cap" + ~placeholder:"amount" + ~default:"0" + ~doc:"Set the burn cap" + (parameter (fun _ s -> + match Tez.of_string s with + | Some t -> + return t + | None -> + failwith "Bad burn cap")) + +let no_waiting_for_endorsements_arg = + switch + ~long:"no-waiting-for-late-endorsements" + ~doc:"Disable waiting for late endorsements" + () + +let await_endorsements_arg = + switch + ~long:"await-late-endorsements" + ~doc:"Await late endorsements when baking a block" + () + +let endorsement_delay_arg = + default_arg + ~long:"endorsement-delay" + ~placeholder:"seconds" + ~doc: + "delay before endorsing blocks\n\ + Delay between notifications of new blocks from the node and production \ + of endorsements for these blocks." + ~default:"5" + (parameter (fun _ s -> + try + let i = int_of_string s in + fail_when (i < 0) (Bad_endorsement_delay s) + >>=? fun () -> return (int_of_string s) + with _ -> fail (Bad_endorsement_delay s))) + +let preserved_levels_arg = + default_arg + ~long:"preserved-levels" + ~placeholder:"threshold" + ~doc:"Number of effective levels kept in the accuser's memory" + ~default:"4096" + (parameter (fun _ s -> + try + let preserved_cycles = int_of_string s in + if preserved_cycles < 0 then fail (Bad_preserved_levels s) + else return preserved_cycles + with _ -> fail (Bad_preserved_levels s))) + +let no_print_source_flag = + switch + ~long:"no-print-source" + ~short:'q' + ~doc: + "don't print the source code\n\ + If an error is encountered, the client will print the contract's \ + source code by default.\n\ + This option disables this behaviour." + () + +let no_confirmation = + switch + ~long:"no-confirmation" + ~doc:"don't print wait for the operation to be confirmed." + () + +let signature_parameter = + parameter (fun _cctxt s -> + match Signature.of_b58check_opt s with + | Some s -> + return s + | None -> + failwith "Not given a valid signature") + +let unparsing_mode_parameter = + parameter + ~autocomplete:(fun _cctxt -> + return ["Readable"; "Optimized"; "Optimized_legacy"]) + (fun _cctxt s -> + match s with + | "Readable" -> + return Script_ir_translator.Readable + | "Optimized" -> + return Script_ir_translator.Optimized + | "Optimized_legacy" -> + return Script_ir_translator.Optimized_legacy + | _ -> + failwith "Unknown unparsing mode %s" s) + +let unparsing_mode_arg ~default = + default_arg + ~long:"unparsing-mode" + ~placeholder:"mode" + ~doc: + "Unparsing mode to use\n\ + One of \"Readable\", \"Optimized\", or \"Optimized_legacy\".\n\ + This option affects the way the values of the following Michelson \ + types are represented:\n\ + - timestamp: the Readable representation is a RFC3339 string, the \ + Optimized and Optimized_legacy representations are the number of \ + seconds since Epoch\n\ + - key, signature, key_hash, address, contract, chain_id: the Readable \ + representation is a Base58Check string, the Optimized and \ + Optimized_legacy representations are byte sequences\n\ + - nested pairs: in Readable mode, the Pair constructor is used even \ + with arity bigger than 2 such as in Pair 0 1 2; in Optimized_legacy \ + mode, the Pair constructor is always use with arity 2 such as in Pair \ + 0 (Pair 1 2); in Optimized mode, a sequence is used if there are at \ + least 4 elements and the behavior is the same as in Optimized_legacy \ + mode otherwise.\n" + ~default + unparsing_mode_parameter + +module Daemon = struct + let baking_switch = + switch ~long:"baking" ~short:'B' ~doc:"run the baking daemon" () + + let endorsement_switch = + switch ~long:"endorsement" ~short:'E' ~doc:"run the endorsement daemon" () + + let denunciation_switch = + switch + ~long:"denunciation" + ~short:'D' + ~doc:"run the denunciation daemon" + () +end diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_args.mli b/src/proto_009_PsFLoren/lib_client/client_proto_args.mli new file mode 100644 index 0000000000000000000000000000000000000000..a095bd9d5e3a9c21b6b83135fbd921ebf9e5de87 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_args.mli @@ -0,0 +1,119 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context + +val tez_sym : string + +val init_arg : (string, full) Clic.arg + +val fee_arg : (Tez.t option, full) Clic.arg + +val default_fee_arg : (Tez.t option, full) Clic.arg + +val counter_arg : (Z.t option, full) Clic.arg + +val gas_limit_arg : (Gas.Arith.integral option, full) Clic.arg + +val default_gas_limit_arg : (Gas.Arith.integral option, full) Clic.arg + +val storage_limit_arg : (Z.t option, full) Clic.arg + +val default_storage_limit_arg : (Z.t option, full) Clic.arg + +val arg_arg : (string option, full) Clic.arg + +val default_arg_arg : (string option, full) Clic.arg + +val source_arg : (string option, full) Clic.arg + +val entrypoint_arg : (string option, full) Clic.arg + +val default_entrypoint_arg : (string option, full) Clic.arg + +val delegate_arg : (Signature.Public_key_hash.t option, full) Clic.arg + +val max_priority_arg : (int option, full) Clic.arg + +val minimal_fees_arg : (Tez.tez, full) Clic.arg + +val minimal_nanotez_per_gas_unit_arg : (Q.t, full) Clic.arg + +val minimal_nanotez_per_byte_arg : (Q.t, full) Clic.arg + +val force_low_fee_arg : (bool, full) Clic.arg + +val fee_cap_arg : (Tez.t, full) Clic.arg + +val burn_cap_arg : (Tez.t, full) Clic.arg + +val no_waiting_for_endorsements_arg : (bool, full) Clic.arg + +val await_endorsements_arg : (bool, full) Clic.arg + +val force_switch : (bool, full) Clic.arg + +val minimal_timestamp_switch : (bool, full) Clic.arg + +val endorsement_delay_arg : (int, full) Clic.arg + +val preserved_levels_arg : (int, full) Clic.arg + +val no_print_source_flag : (bool, full) Clic.arg + +val no_confirmation : (bool, full) Clic.arg + +val tez_arg : + default:string -> parameter:string -> doc:string -> (Tez.t, full) Clic.arg + +val tez_param : + name:string -> + desc:string -> + ('a, full) Clic.params -> + (Tez.t -> 'a, full) Clic.params + +val signature_parameter : (Signature.t, full) Clic.parameter + +module Daemon : sig + val baking_switch : (bool, full) Clic.arg + + val endorsement_switch : (bool, full) Clic.arg + + val denunciation_switch : (bool, full) Clic.arg +end + +val int_parameter : (int, full) Clic.parameter + +val string_parameter : (string, full) Clic.parameter + +val bytes_of_prefixed_string : string -> Bytes.t tzresult Lwt.t + +val bytes_parameter : (Bytes.t, full) Clic.parameter + +val unparsing_mode_arg : + default:string -> (Script_ir_translator.unparsing_mode, full) Clic.arg diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_context.ml b/src/proto_009_PsFLoren/lib_client/client_proto_context.ml new file mode 100644 index 0000000000000000000000000000000000000000..6c4ad33bc3578b3894a1011832e4180128dcf8f2 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_context.ml @@ -0,0 +1,644 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context +open Tezos_micheline +open Client_proto_contracts +open Client_keys + +let get_balance (rpc : #rpc_context) ~chain ~block contract = + Alpha_services.Contract.balance rpc (chain, block) contract + +let get_storage (rpc : #rpc_context) ~chain ~block contract = + Alpha_services.Contract.storage_opt rpc (chain, block) contract + +let get_big_map_value (rpc : #rpc_context) ~chain ~block id key = + Alpha_services.Contract.big_map_get rpc (chain, block) id key + +let get_contract_big_map_value (rpc : #rpc_context) ~chain ~block contract key + = + Alpha_services.Contract.contract_big_map_get_opt + rpc + (chain, block) + contract + key + +let get_script (rpc : #rpc_context) ~chain ~block contract = + Alpha_services.Contract.script_opt rpc (chain, block) contract + +let parse_expression arg = + Lwt.return + (Micheline_parser.no_parsing_error + (Michelson_v1_parser.parse_expression arg)) + +let parse_arg_transfer arg = + ( match arg with + | Some arg -> + parse_expression arg >>=? fun {expanded = arg; _} -> return_some arg + | None -> + return_none ) + >>=? fun parameters -> + return + (Option.fold ~some:Script.lazy_expr ~none:Script.unit_parameter parameters) + +let build_transaction_operation ~amount ~parameters ?(entrypoint = "default") + ?fee ?gas_limit ?storage_limit destination = + let operation = Transaction {amount; parameters; destination; entrypoint} in + Injection.prepare_manager_operation ?fee ?gas_limit ?storage_limit operation + +let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?branch ~source ~src_pk ~src_sk ~destination + ?(entrypoint = "default") ?arg ~amount ?fee ?gas_limit ?storage_limit + ?counter ~fee_parameter () = + parse_arg_transfer arg + >>=? fun parameters -> + let contents = + build_transaction_operation + ~amount + ~parameters + ~entrypoint + ?fee + ?gas_limit + ?storage_limit + destination + in + let contents = Injection.Single_manager contents in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?branch + ~source + ?fee + ?gas_limit + ?storage_limit + ?counter + ~src_pk + ~src_sk + ~fee_parameter + contents + >>=? fun (oph, op, result) -> + Lwt.return (Injection.originated_contracts result) + >>=? fun contracts -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return ((oph, op, result), contracts) + +let build_reveal_operation ?fee ?gas_limit ?storage_limit pk = + let operation = Reveal pk in + Injection.prepare_manager_operation ?fee ?gas_limit ?storage_limit operation + +let reveal cctxt ~chain ~block ?confirmations ?dry_run ?verbose_signing ?branch + ~source ~src_pk ~src_sk ?fee ~fee_parameter () = + let contents = + Injection.Single_manager + (build_reveal_operation ?fee ~storage_limit:Z.zero src_pk) + in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?branch + ~source + ?fee + ~src_pk + ~src_sk + ~fee_parameter + contents + >>=? fun (oph, op, result) -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let build_delegate_operation ?fee ?gas_limit ?(storage_limit = Z.zero) + delegate_opt = + let operation = Delegation delegate_opt in + Injection.prepare_manager_operation ?fee ?gas_limit ~storage_limit operation + +let delegate_contract cctxt ~chain ~block ?branch ?confirmations ?dry_run + ?verbose_signing ~source ~src_pk ~src_sk ?fee ~fee_parameter delegate_opt = + let operation = + Injection.Single_manager + (build_delegate_operation ?fee ~storage_limit:Z.zero delegate_opt) + in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?branch + ~source + ?fee + ~storage_limit:Z.zero + ~src_pk + ~src_sk + ~fee_parameter + operation + >>=? fun (oph, op, result) -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let list_contract_labels cctxt ~chain ~block = + Alpha_services.Contract.list cctxt (chain, block) + >>=? fun contracts -> + List.rev_map_es + (fun h -> + ( match Contract.is_implicit h with + | Some m -> ( + Public_key_hash.rev_find cctxt m + >>=? function + | None -> + return "" + | Some nm -> ( + RawContractAlias.find_opt cctxt nm + >>=? function + | None -> + return (" (known as " ^ nm ^ ")") + | Some _ -> + return (" (known as key:" ^ nm ^ ")") ) ) + | None -> ( + RawContractAlias.rev_find cctxt h + >>=? function + | None -> return "" | Some nm -> return (" (known as " ^ nm ^ ")") ) + ) + >>=? fun nm -> + let kind = + match Contract.is_implicit h with + | Some _ -> + " (implicit)" + | None -> + "" + in + let h_b58 = Contract.to_b58check h in + return (nm, h_b58, kind)) + contracts + >|=? List.rev + +let message_added_contract (cctxt : #full) name = + cctxt#message "Contract memorized as %s." name + +let set_delegate cctxt ~chain ~block ?confirmations ?dry_run ?verbose_signing + ?fee contract ~src_pk ~manager_sk ~fee_parameter opt_delegate = + delegate_contract + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ~source:contract + ~src_pk + ~src_sk:manager_sk + ?fee + ~fee_parameter + opt_delegate + +let register_as_delegate cctxt ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?fee ~manager_sk ~fee_parameter src_pk = + let source = Signature.Public_key.hash src_pk in + delegate_contract + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ~source + ~src_pk + ~src_sk:manager_sk + ?fee + ~fee_parameter + (Some source) + +let save_contract ~force cctxt alias_name contract = + RawContractAlias.add ~force cctxt alias_name contract + >>=? fun () -> + message_added_contract cctxt alias_name >>= fun () -> return_unit + +let build_origination_operation ?fee ?gas_limit ?storage_limit ~initial_storage + ~code ~delegate ~balance () = + (* With the change of making implicit accounts delegatable, the following + 3 arguments are being defaulted before they can be safely removed. *) + Lwt.return (Michelson_v1_parser.parse_expression initial_storage) + >>= fun result -> + Lwt.return (Micheline_parser.no_parsing_error result) + >>=? fun {Michelson_v1_parser.expanded = storage; _} -> + let code = Script.lazy_expr code and storage = Script.lazy_expr storage in + let origination = + Origination + { + delegate; + script = {code; storage}; + credit = balance; + preorigination = None; + } + in + return + (Injection.prepare_manager_operation + ?fee + ?gas_limit + ?storage_limit + origination) + +let originate_contract (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?branch ?fee ?gas_limit ?storage_limit ~delegate + ~initial_storage ~balance ~source ~src_pk ~src_sk ~code ~fee_parameter () = + build_origination_operation + ?fee + ?gas_limit + ?storage_limit + ~initial_storage + ~code + ~delegate + ~balance + () + >>=? fun origination -> + let origination = Injection.Single_manager origination in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?branch + ~source + ?fee + ?gas_limit + ?storage_limit + ~src_pk + ~src_sk + ~fee_parameter + origination + >>=? fun (oph, op, result) -> + ( match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) ) + >>=? fun res -> + Lwt.return (Injection.originated_contracts result) + >>=? function + | [contract] -> + return (res, contract) + | contracts -> + failwith + "The origination introduced %d contracts instead of one." + (List.length contracts) + +type activation_key = { + pkh : Ed25519.Public_key_hash.t; + amount : Tez.t; + activation_code : Blinded_public_key_hash.activation_code; + mnemonic : string list; + password : string; + email : string; +} + +let raw_activation_key_encoding = + let open Data_encoding in + obj6 + (req "pkh" Ed25519.Public_key_hash.encoding) + (req "amount" Tez.encoding) + (req "activation_code" Blinded_public_key_hash.activation_code_encoding) + (req "mnemonic" (list string)) + (req "password" string) + (req "email" string) + +let activation_key_encoding = + (* Hack: allow compatibility with older encoding *) + let open Data_encoding in + conv + (fun {pkh; amount; activation_code; mnemonic; password; email} -> + (pkh, amount, activation_code, mnemonic, password, email)) + (fun (pkh, amount, activation_code, mnemonic, password, email) -> + {pkh; amount; activation_code; mnemonic; password; email}) + @@ splitted + ~binary:raw_activation_key_encoding + ~json: + (union + [ case + ~title:"Activation" + Json_only + raw_activation_key_encoding + (fun x -> Some x) + (fun x -> x); + case + ~title:"Deprecated_activation" + Json_only + (obj6 + (req "pkh" Ed25519.Public_key_hash.encoding) + (req "amount" Tez.encoding) + (req + "secret" + Blinded_public_key_hash.activation_code_encoding) + (req "mnemonic" (list string)) + (req "password" string) + (req "email" string)) + (fun _ -> None) + (fun x -> x) ]) + +type batch_transfer_operation = { + destination : string; + fee : string option; + gas_limit : Gas.Arith.integral option; + storage_limit : Z.t option; + amount : string; + arg : string option; + entrypoint : string option; +} + +let batch_transfer_operation_encoding = + let open Data_encoding in + conv + (fun {destination; fee; gas_limit; storage_limit; amount; arg; entrypoint} -> + (destination, fee, gas_limit, storage_limit, amount, arg, entrypoint)) + (fun (destination, fee, gas_limit, storage_limit, amount, arg, entrypoint) -> + {destination; fee; gas_limit; storage_limit; amount; arg; entrypoint}) + (obj7 + (req "destination" string) + (opt "fee" string) + (opt "gas-limit" Gas.Arith.n_integral_encoding) + (opt "storage-limit" z) + (req "amount" string) + (opt "arg" string) + (opt "entrypoint" string)) + +let read_key key = + match Bip39.of_words key.mnemonic with + | None -> + failwith "" + | Some t -> + (* TODO: unicode normalization (NFKD)... *) + let passphrase = + Bytes.(cat (of_string key.email) (of_string key.password)) + in + let sk = Bip39.to_seed ~passphrase t in + let sk = Bytes.sub sk 0 32 in + let sk : Signature.Secret_key.t = + Ed25519 + (Data_encoding.Binary.of_bytes_exn Ed25519.Secret_key.encoding sk) + in + let pk = Signature.Secret_key.to_public_key sk in + let pkh = Signature.Public_key.hash pk in + return (pkh, pk, sk) + +let inject_activate_operation cctxt ~chain ~block ?confirmations ?dry_run alias + pkh activation_code = + let contents = Single (Activate_account {id = pkh; activation_code}) in + Injection.inject_operation + cctxt + ?confirmations + ?dry_run + ~chain + ~block + ~fee_parameter:Injection.dummy_fee_parameter + contents + ~unspecified_gas_limit:false + ~unspecified_storage_limit:false + >>=? fun (oph, op, result) -> + ( match confirmations with + | None -> + return_unit + | Some _confirmations -> + Alpha_services.Contract.balance + cctxt + (chain, block) + (Contract.implicit_contract (Ed25519 pkh)) + >>=? fun balance -> + cctxt#message + "Account %s (%a) activated with %s%a." + alias + Ed25519.Public_key_hash.pp + pkh + Client_proto_args.tez_sym + Tez.pp + balance + >>= fun () -> return_unit ) + >>=? fun () -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Activate_account _ as op), result) -> + return (oph, op, result) + +let activate_account (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?(encrypted = false) ?force key name = + read_key key + >>=? fun (pkh, pk, sk) -> + fail_unless + (Signature.Public_key_hash.equal pkh (Ed25519 key.pkh)) + (failure + "@[Inconsistent activation key:@ Computed pkh: %a@ Embedded pkh: \ + %a @]" + Signature.Public_key_hash.pp + pkh + Ed25519.Public_key_hash.pp + key.pkh) + >>=? fun () -> + Tezos_signer_backends.Unencrypted.make_pk pk + >>=? fun pk_uri -> + ( if encrypted then Tezos_signer_backends.Encrypted.encrypt cctxt sk + else Tezos_signer_backends.Unencrypted.make_sk sk ) + >>=? fun sk_uri -> + Client_keys.register_key cctxt ?force (pkh, pk_uri, sk_uri) name + >>=? fun () -> + inject_activate_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + name + key.pkh + key.activation_code + +let activate_existing_account (cctxt : #full) ~chain ~block ?confirmations + ?dry_run alias activation_code = + Client_keys.alias_keys cctxt alias + >>=? function + | Some (Ed25519 pkh, _, _) -> + inject_activate_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + alias + pkh + activation_code + | Some _ -> + failwith "Only Ed25519 accounts can be activated" + | None -> + failwith "Unknown account" + +type period_info = { + current_period_kind : Voting_period.kind; + position : Int32.t; + remaining : Int32.t; + current_proposal : Protocol_hash.t option; +} + +type ballots_info = { + current_quorum : Int32.t; + participation : Int32.t; + supermajority : Int32.t; + ballots : Vote.ballots; +} + +let get_ballots_info (cctxt : #full) ~chain ~block = + (* Get the next level, not the current *) + let cb = (chain, block) in + Alpha_services.Voting.ballots cctxt cb + >>=? fun ballots -> + Alpha_services.Voting.current_quorum cctxt cb + >>=? fun current_quorum -> + Alpha_services.Voting.listings cctxt cb + >>=? fun listings -> + let max_participation = + List.fold_left (fun acc (_, w) -> Int32.add w acc) 0l listings + in + let all_votes = Int32.(add (add ballots.yay ballots.nay) ballots.pass) in + let participation = Int32.(div (mul all_votes 100_00l) max_participation) in + let supermajority = Int32.(div (mul 8l (add ballots.yay ballots.nay)) 10l) in + return {current_quorum; participation; supermajority; ballots} + +let get_period_info ?(successor = false) (cctxt : #full) ~chain ~block = + let cb = (chain, block) in + ( if successor then Alpha_services.Voting.successor_period + else Alpha_services.Voting.current_period ) + cctxt + cb + >>=? fun voting_period -> + Alpha_services.Voting.current_proposal cctxt cb + >>=? fun current_proposal -> + return + { + current_period_kind = voting_period.voting_period.kind; + position = voting_period.position; + remaining = voting_period.remaining; + current_proposal; + } + +let get_proposals (cctxt : #full) ~chain ~block = + let cb = (chain, block) in + Alpha_services.Voting.proposals cctxt cb + +let submit_proposals ?dry_run ?verbose_signing (cctxt : #full) ~chain ~block + ?confirmations ~src_sk source proposals = + Alpha_services.Voting.successor_period cctxt (chain, block) + >>=? fun {voting_period = {index; _}; _} -> + let contents = Single (Proposals {source; period = index; proposals}) in + Injection.inject_operation + cctxt + ~chain + ~block + ?confirmations + ~fee_parameter:Injection.dummy_fee_parameter + ?dry_run + ~src_sk + contents + ?verbose_signing + ~unspecified_gas_limit:false + ~unspecified_storage_limit:false + +let submit_ballot ?dry_run ?verbose_signing (cctxt : #full) ~chain ~block + ?confirmations ~src_sk source proposal ballot = + (* The user must provide the proposal explicitly to make himself sure + for what he is voting. *) + Alpha_services.Voting.successor_period cctxt (chain, block) + >>=? fun {voting_period = {index; _}; _} -> + let contents = Single (Ballot {source; period = index; proposal; ballot}) in + Injection.inject_operation + cctxt + ~chain + ~block + ?confirmations + ~fee_parameter:Injection.dummy_fee_parameter + ?dry_run + ~src_sk + contents + ?verbose_signing + ~unspecified_gas_limit:false + ~unspecified_storage_limit:false + +let pp_operation formatter (a : Alpha_block_services.operation) = + match (a.receipt, a.protocol_data) with + | (Some (Apply_results.Operation_metadata omd), Operation_data od) -> ( + match Apply_results.kind_equal_list od.contents omd.contents with + | Some Apply_results.Eq -> + Operation_result.pp_operation_result + formatter + (od.contents, omd.contents) + | None -> + Stdlib.failwith "Unexpected result." ) + | (None, _) -> + Stdlib.failwith + "Pruned metadata: the operation receipt was removed accordingly to \ + the node's history mode." + | _ -> + Stdlib.failwith "Unexpected result." + +let get_operation_from_block (cctxt : #full) ~chain predecessors operation_hash + = + Client_confirmations.lookup_operation_in_previous_blocks + cctxt + ~chain + ~predecessors + operation_hash + >>=? function + | None -> + return_none + | Some (block, i, j) -> + cctxt#message + "Operation found in block: %a (pass: %d, offset: %d)" + Block_hash.pp + block + i + j + >>= fun () -> + Protocol_client_context.Alpha_block_services.Operations.operation + cctxt + ~chain + ~block:(`Hash (block, 0)) + i + j + >>=? fun op' -> return_some op' + +let display_receipt_for_operation (cctxt : #full) ~chain ?(predecessors = 10) + operation_hash = + get_operation_from_block cctxt ~chain predecessors operation_hash + >>=? function + | None -> + failwith "Couldn't find operation" + | Some op -> + cctxt#message "%a" pp_operation op >>= fun () -> return_unit diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_context.mli b/src/proto_009_PsFLoren/lib_client/client_proto_context.mli new file mode 100644 index 0000000000000000000000000000000000000000..1c09a136e61fa37658e3f218c168854bfdcee0c3 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_context.mli @@ -0,0 +1,306 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +val list_contract_labels : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + (string * string * string) list tzresult Lwt.t + +val get_storage : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + Script.expr option tzresult Lwt.t + +val get_contract_big_map_value : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + Script.expr * Script.expr -> + Script.expr option tzresult Lwt.t + +val get_big_map_value : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Big_map.Id.t -> + Script_expr_hash.t -> + Script.expr tzresult Lwt.t + +val get_script : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + Script.t option tzresult Lwt.t + +val get_balance : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + Tez.t tzresult Lwt.t + +val build_delegate_operation : + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + public_key_hash option -> + Kind.delegation Injection.annotated_manager_operation + +val set_delegate : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?fee:Tez.tez -> + public_key_hash -> + src_pk:public_key -> + manager_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + public_key_hash option -> + Kind.delegation Kind.manager Injection.result tzresult Lwt.t + +val register_as_delegate : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?fee:Tez.tez -> + manager_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + public_key -> + Kind.delegation Kind.manager Injection.result tzresult Lwt.t + +val save_contract : + force:bool -> + #Protocol_client_context.full -> + string -> + Contract.t -> + unit tzresult Lwt.t + +val originate_contract : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + delegate:public_key_hash option -> + initial_storage:string -> + balance:Tez.t -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + code:Script.expr -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.origination Kind.manager Injection.result * Contract.t) tzresult Lwt.t + +val parse_arg_transfer : string option -> Script.lazy_expr tzresult Lwt.t + +val build_transaction_operation : + amount:Tez.t -> + parameters:Script.lazy_expr -> + ?entrypoint:string -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + Contract.t -> + Kind.transaction Injection.annotated_manager_operation + +val transfer : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + destination:Contract.t -> + ?entrypoint:string -> + ?arg:string -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Z.t -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract.t list) tzresult + Lwt.t + +val build_reveal_operation : + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + public_key -> + Kind.reveal Injection.annotated_manager_operation + +val reveal : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + ?fee:Tez.t -> + fee_parameter:Injection.fee_parameter -> + unit -> + Kind.reveal Kind.manager Injection.result tzresult Lwt.t + +type activation_key = { + pkh : Ed25519.Public_key_hash.t; + amount : Tez.t; + activation_code : Blinded_public_key_hash.activation_code; + mnemonic : string list; + password : string; + email : string; +} + +val activation_key_encoding : activation_key Data_encoding.t + +type batch_transfer_operation = { + destination : string; + fee : string option; + gas_limit : Gas.Arith.integral option; + storage_limit : Z.t option; + amount : string; + arg : string option; + entrypoint : string option; +} + +val batch_transfer_operation_encoding : + batch_transfer_operation Data_encoding.t + +val activate_account : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?encrypted:bool -> + ?force:bool -> + activation_key -> + string -> + Kind.activate_account Injection.result tzresult Lwt.t + +val activate_existing_account : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + string -> + Blinded_public_key_hash.activation_code -> + Kind.activate_account Injection.result tzresult Lwt.t + +type period_info = { + current_period_kind : Voting_period.kind; + position : Int32.t; + remaining : Int32.t; + current_proposal : Protocol_hash.t option; +} + +type ballots_info = { + current_quorum : Int32.t; + participation : Int32.t; + supermajority : Int32.t; + ballots : Vote.ballots; +} + +val get_period_info : + ?successor:bool -> + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + period_info tzresult Lwt.t + +val get_ballots_info : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ballots_info tzresult Lwt.t + +val get_proposals : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Int32.t Environment.Protocol_hash.Map.t tzresult Lwt.t + +val submit_proposals : + ?dry_run:bool -> + ?verbose_signing:bool -> + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + src_sk:Client_keys.sk_uri -> + public_key_hash -> + Protocol_hash.t list -> + Kind.proposals Injection.result_list tzresult Lwt.t + +val submit_ballot : + ?dry_run:bool -> + ?verbose_signing:bool -> + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + src_sk:Client_keys.sk_uri -> + public_key_hash -> + Protocol_hash.t -> + Vote.ballot -> + Kind.ballot Injection.result_list tzresult Lwt.t + +(** lookup an operation in [predecessors] previous blocks, and print the + receipt if found *) +val display_receipt_for_operation : + #Protocol_client_context.full -> + chain:Block_services.chain -> + ?predecessors:int -> + Operation_list_hash.elt -> + unit tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_contracts.ml b/src/proto_009_PsFLoren/lib_client/client_proto_contracts.ml new file mode 100644 index 0000000000000000000000000000000000000000..0bcf748a89eded313f20192f4f7be3b6e0407ea1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_contracts.ml @@ -0,0 +1,173 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module ContractEntity = struct + type t = Contract.t + + let encoding = Contract.encoding + + let of_source s = + Contract.of_b58check s |> Environment.wrap_tzresult + |> record_trace (failure "bad contract notation") + |> Lwt.return + + let to_source s = return (Contract.to_b58check s) + + let name = "contract" +end + +module RawContractAlias = Client_aliases.Alias (ContractEntity) + +module ContractAlias = struct + let find cctxt s = + RawContractAlias.find_opt cctxt s + >>=? function + | Some v -> + return (s, v) + | None -> ( + Client_keys.Public_key_hash.find_opt cctxt s + >>=? function + | Some v -> + return (s, Contract.implicit_contract v) + | None -> + failwith "no contract or key named %s" s ) + + let find_key cctxt name = + Client_keys.Public_key_hash.find cctxt name + >>=? fun v -> return (name, Contract.implicit_contract v) + + let rev_find cctxt c = + match Contract.is_implicit c with + | Some hash -> ( + Client_keys.Public_key_hash.rev_find cctxt hash + >>=? function + | Some name -> return_some ("key:" ^ name) | None -> return_none ) + | None -> + RawContractAlias.rev_find cctxt c + + let get_contract cctxt s = + match String.split ~limit:1 ':' s with + | ["key"; key] -> + find_key cctxt key + | _ -> + find cctxt s + + let autocomplete cctxt = + Client_keys.Public_key_hash.autocomplete cctxt + >>=? fun keys -> + RawContractAlias.autocomplete cctxt + >>=? fun contracts -> return (List.map (( ^ ) "key:") keys @ contracts) + + let alias_param ?(name = "name") ?(desc = "existing contract alias") next = + let desc = + desc ^ "\n" + ^ "Can be a contract alias or a key alias (autodetected in order).\n\ + Use 'key:name' to force the later." + in + Clic.( + param + ~name + ~desc + (parameter ~autocomplete (fun cctxt p -> get_contract cctxt p)) + next) + + let find_destination cctxt s = + match String.split ~limit:1 ':' s with + | ["alias"; alias] -> + find cctxt alias + | ["key"; text] -> + Client_keys.Public_key_hash.find cctxt text + >>=? fun v -> return (s, Contract.implicit_contract v) + | _ -> ( + find cctxt s + >>= function + | Ok v -> + return v + | Error k_errs -> ( + ContractEntity.of_source s + >>= function + | Ok v -> + return (s, v) + | Error c_errs -> + Lwt.return_error (k_errs @ c_errs) ) ) + + let destination_parameter () = + Clic.parameter + ~autocomplete:(fun cctxt -> + autocomplete cctxt + >>=? fun list1 -> + Client_keys.Public_key_hash.autocomplete cctxt + >>=? fun list2 -> return (list1 @ list2)) + find_destination + + let destination_param ?(name = "dst") ?(desc = "destination contract") next = + let desc = + String.concat + "\n" + [ desc; + "Can be an alias, a key, or a literal (autodetected in order).\n\ + Use 'text:literal', 'alias:name', 'key:name' to force." ] + in + Clic.param ~name ~desc (destination_parameter ()) next + + let destination_arg ?(name = "dst") ?(doc = "destination contract") () = + let doc = + String.concat + "\n" + [ doc; + "Can be an alias, a key, or a literal (autodetected in order).\n\ + Use 'text:literal', 'alias:name', 'key:name' to force." ] + in + Clic.arg ~long:name ~doc ~placeholder:name (destination_parameter ()) + + let name cctxt contract = + rev_find cctxt contract + >>=? function + | None -> return (Contract.to_b58check contract) | Some name -> return name +end + +let list_contracts cctxt = + RawContractAlias.load cctxt + >>=? fun raw_contracts -> + List.map_s (fun (n, v) -> Lwt.return ("", n, v)) raw_contracts + >>= fun contracts -> + Client_keys.Public_key_hash.load cctxt + >>=? fun keys -> + (* List accounts (implicit contracts of identities) *) + List.map_es + (fun (n, v) -> + RawContractAlias.mem cctxt n + >>=? fun mem -> + let p = if mem then "key:" else "" in + let v' = Contract.implicit_contract v in + return (p, n, v')) + keys + >>=? fun accounts -> return (contracts @ accounts) + +let get_delegate cctxt ~chain ~block source = + Alpha_services.Contract.delegate_opt cctxt (chain, block) source diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_contracts.mli b/src/proto_009_PsFLoren/lib_client/client_proto_contracts.mli new file mode 100644 index 0000000000000000000000000000000000000000..fcef44b21f112a289c4f087601da62b55027f7e8 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_contracts.mli @@ -0,0 +1,74 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Clic + +module RawContractAlias : Client_aliases.Alias with type t = Contract.t + +module ContractAlias : sig + val get_contract : + #Client_context.wallet -> string -> (string * Contract.t) tzresult Lwt.t + + val alias_param : + ?name:string -> + ?desc:string -> + ('a, (#Client_context.wallet as 'wallet)) params -> + (string * Contract.t -> 'a, 'wallet) params + + val find_destination : + #Client_context.wallet -> string -> (string * Contract.t) tzresult Lwt.t + + val destination_param : + ?name:string -> + ?desc:string -> + ('a, (#Client_context.wallet as 'wallet)) params -> + (string * Contract.t -> 'a, 'wallet) params + + val destination_arg : + ?name:string -> + ?doc:string -> + unit -> + ((string * Contract.t) option, #Client_context.wallet) Clic.arg + + val rev_find : + #Client_context.wallet -> Contract.t -> string option tzresult Lwt.t + + val name : #Client_context.wallet -> Contract.t -> string tzresult Lwt.t + + val autocomplete : #Client_context.wallet -> string list tzresult Lwt.t +end + +val list_contracts : + #Client_context.wallet -> + (string * string * RawContractAlias.t) list tzresult Lwt.t + +val get_delegate : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + public_key_hash option tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_multisig.ml b/src/proto_009_PsFLoren/lib_client/client_proto_multisig.ml new file mode 100644 index 0000000000000000000000000000000000000000..508283d7d088c9f91f99d5f54b6d63c1bf3b61b1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_multisig.ml @@ -0,0 +1,918 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Protocol +open Alpha_context + +type error += Contract_has_no_script of Contract.t + +type error += + | Not_a_supported_multisig_contract of (Script_expr_hash.t * Script.expr) + +type error += Contract_has_no_storage of Contract.t + +type error += Contract_has_unexpected_storage of Contract.t + +type error += Invalid_signature of signature + +type error += Not_enough_signatures of int * int + +type error += Action_deserialisation_error of Script.expr + +type error += Bytes_deserialisation_error of Bytes.t + +type error += Bad_deserialized_contract of (Contract.t * Contract.t) + +type error += Bad_deserialized_counter of (counter * counter) + +type error += Non_positive_threshold of int + +type error += Threshold_too_high of int * int + +let () = + register_error_kind + `Permanent + ~id:"contractHasNoScript" + ~title: + "The given contract is not a multisig contract because it has no script" + ~description: + "A multisig command has referenced a scriptless smart contract instead \ + of a multisig smart contract." + ~pp:(fun ppf contract -> + Format.fprintf ppf "Contract has no script %a." Contract.pp contract) + Data_encoding.(obj1 (req "contract" Contract.encoding)) + (function Contract_has_no_script c -> Some c | _ -> None) + (fun c -> Contract_has_no_script c) ; + register_error_kind + `Permanent + ~id:"notASupportedMultisigContract" + ~title:"The given contract is not one of the supported contracts" + ~description: + "A multisig command has referenced a smart contract whose script is not \ + one of the known multisig contract scripts." + ~pp:(fun ppf (hash, script) -> + Format.fprintf + ppf + "Not a supported multisig contract %a.@\n\ + The hash of this script is 0x%a, it was not found among in the list \ + of known multisig script hashes." + Michelson_v1_printer.print_expr + script + Hex.pp + (Script_expr_hash.to_bytes hash |> Hex.of_bytes)) + Data_encoding.( + obj2 + (req "hash" Script_expr_hash.encoding) + (req "script" Script.expr_encoding)) + (function + | Not_a_supported_multisig_contract (h, c) -> Some (h, c) | _ -> None) + (fun (h, c) -> Not_a_supported_multisig_contract (h, c)) ; + register_error_kind + `Permanent + ~id:"contractHasNoStorage" + ~title: + "The given contract is not a multisig contract because it has no storage" + ~description: + "A multisig command has referenced a smart contract without storage \ + instead of a multisig smart contract." + ~pp:(fun ppf contract -> + Format.fprintf ppf "Contract has no storage %a." Contract.pp contract) + Data_encoding.(obj1 (req "contract" Contract.encoding)) + (function Contract_has_no_storage c -> Some c | _ -> None) + (fun c -> Contract_has_no_storage c) ; + register_error_kind + `Permanent + ~id:"contractHasUnexpectedStorage" + ~title: + "The storage of the given contract is not of the shape expected for a \ + multisig contract" + ~description: + "A multisig command has referenced a smart contract whose storage is of \ + a different shape than the expected one." + ~pp:(fun ppf contract -> + Format.fprintf + ppf + "Contract has unexpected storage %a." + Contract.pp + contract) + Data_encoding.(obj1 (req "contract" Contract.encoding)) + (function Contract_has_unexpected_storage c -> Some c | _ -> None) + (fun c -> Contract_has_unexpected_storage c) ; + register_error_kind + `Permanent + ~id:"invalidSignature" + ~title: + "The following signature did not match a public key in the given \ + multisig contract" + ~description: + "A signature was given for a multisig contract that matched none of the \ + public keys of the contract signers" + ~pp:(fun ppf s -> + Format.fprintf ppf "Invalid signature %s." (Signature.to_b58check s)) + Data_encoding.(obj1 (req "invalid_signature" Signature.encoding)) + (function Invalid_signature s -> Some s | _ -> None) + (fun s -> Invalid_signature s) ; + register_error_kind + `Permanent + ~id:"notEnoughSignatures" + ~title:"Not enough signatures were provided for this multisig action" + ~description: + "To run an action on a multisig contract, you should provide at least \ + as many signatures as indicated by the threshold stored in the \ + multisig contract." + ~pp:(fun ppf (threshold, nsigs) -> + Format.fprintf + ppf + "Not enough signatures: only %d signatures were given but the \ + threshold is currently %d" + nsigs + threshold) + Data_encoding.(obj1 (req "threshold_nsigs" (tup2 int31 int31))) + (function + | Not_enough_signatures (threshold, nsigs) -> + Some (threshold, nsigs) + | _ -> + None) + (fun (threshold, nsigs) -> Not_enough_signatures (threshold, nsigs)) ; + register_error_kind + `Permanent + ~id:"actionDeserialisation" + ~title:"The expression is not a valid multisig action" + ~description: + "When trying to deserialise an action from a sequence of bytes, we got \ + an expression that does not correspond to a known multisig action" + ~pp:(fun ppf e -> + Format.fprintf + ppf + "Action deserialisation error %a." + Michelson_v1_printer.print_expr + e) + Data_encoding.(obj1 (req "expr" Script.expr_encoding)) + (function Action_deserialisation_error e -> Some e | _ -> None) + (fun e -> Action_deserialisation_error e) ; + register_error_kind + `Permanent + ~id:"bytesDeserialisation" + ~title:"The byte sequence is not a valid multisig action" + ~description: + "When trying to deserialise an action from a sequence of bytes, we got \ + an error" + ~pp:(fun ppf b -> + Format.fprintf ppf "Bytes deserialisation error %s." (Bytes.to_string b)) + Data_encoding.(obj1 (req "expr" bytes)) + (function Bytes_deserialisation_error b -> Some b | _ -> None) + (fun b -> Bytes_deserialisation_error b) ; + register_error_kind + `Permanent + ~id:"badDeserializedContract" + ~title:"The byte sequence is not for the given multisig contract" + ~description: + "When trying to deserialise an action from a sequence of bytes, we got \ + an action for another multisig contract" + ~pp:(fun ppf (received, expected) -> + Format.fprintf + ppf + "Bad deserialized contract, received %a expected %a." + Contract.pp + received + Contract.pp + expected) + Data_encoding.( + obj1 (req "received_expected" (tup2 Contract.encoding Contract.encoding))) + (function Bad_deserialized_contract b -> Some b | _ -> None) + (fun b -> Bad_deserialized_contract b) ; + register_error_kind + `Permanent + ~id:"Bad deserialized counter" + ~title:"Deserialized counter does not match the stored one" + ~description: + "The byte sequence references a multisig counter that does not match \ + the one currently stored in the given multisig contract" + ~pp:(fun ppf (received, expected) -> + Format.fprintf + ppf + "Bad deserialized counter, received %d expected %d." + received + expected) + Data_encoding.(obj1 (req "received_expected" (tup2 int31 int31))) + (function + | Bad_deserialized_counter (c1, c2) -> + Some (Z.to_int c1, Z.to_int c2) + | _ -> + None) + (fun (c1, c2) -> Bad_deserialized_counter (Z.of_int c1, Z.of_int c2)) ; + register_error_kind + `Permanent + ~id:"thresholdTooHigh" + ~title:"Given threshold is too high" + ~description: + "The given threshold is higher than the number of keys, this would lead \ + to a frozen multisig contract" + ~pp:(fun ppf (threshold, nkeys) -> + Format.fprintf + ppf + "Threshold too high: %d expected at most %d." + threshold + nkeys) + Data_encoding.(obj1 (req "received_expected" (tup2 int31 int31))) + (function Threshold_too_high (c1, c2) -> Some (c1, c2) | _ -> None) + (fun (c1, c2) -> Threshold_too_high (c1, c2)) ; + register_error_kind + `Permanent + ~id:"nonPositiveThreshold" + ~title:"Given threshold is not positive" + ~description:"A multisig threshold should be a positive number" + ~pp:(fun ppf threshold -> + Format.fprintf ppf "Multisig threshold %d should be positive." threshold) + Data_encoding.(obj1 (req "threshold" int31)) + (function Non_positive_threshold t -> Some t | _ -> None) + (fun t -> Non_positive_threshold t) + +(* The multisig contract script written by Arthur Breitman + https://github.com/murbard/smart-contracts/blob/master/multisig/michelson/multisig.tz *) +(* Updated to take the chain id into account *) +let multisig_script_string = + "parameter (pair\n\ + \ (pair :payload\n\ + \ (nat %counter) # counter, used to prevent replay attacks\n\ + \ (or :action # payload to sign, represents the requested \ + action\n\ + \ (pair :transfer # transfer tokens\n\ + \ (mutez %amount) # amount to transfer\n\ + \ (contract %dest unit)) # destination to transfer to\n\ + \ (or\n\ + \ (option %delegate key_hash) # change the delegate to \ + this address\n\ + \ (pair %change_keys # change the keys \ + controlling the multisig\n\ + \ (nat %threshold) # new threshold\n\ + \ (list %keys key))))) # new list of keys\n\ + \ (list %sigs (option signature))); # signatures\n\n\ + storage (pair (nat %stored_counter) (pair (nat %threshold) (list %keys \ + key))) ;\n\n\ + code\n\ + \ {\n\ + \ UNPAIR ; SWAP ; DUP ; DIP { SWAP } ;\n\ + \ DIP\n\ + \ {\n\ + \ UNPAIR ;\n\ + \ # pair the payload with the current contract address, to ensure \ + signatures\n\ + \ # can't be replayed across different contracts if a key is reused.\n\ + \ DUP ; SELF ; ADDRESS ; CHAIN_ID ; PAIR ; PAIR ;\n\ + \ PACK ; # form the binary payload that we expect to be signed\n\ + \ DIP { UNPAIR @counter ; DIP { SWAP } } ; SWAP\n\ + \ } ;\n\n\ + \ # Check that the counters match\n\ + \ UNPAIR @stored_counter; DIP { SWAP };\n\ + \ ASSERT_CMPEQ ;\n\n\ + \ # Compute the number of valid signatures\n\ + \ DIP { SWAP } ; UNPAIR @threshold @keys;\n\ + \ DIP\n\ + \ {\n\ + \ # Running count of valid signatures\n\ + \ PUSH @valid nat 0; SWAP ;\n\ + \ ITER\n\ + \ {\n\ + \ DIP { SWAP } ; SWAP ;\n\ + \ IF_CONS\n\ + \ {\n\ + \ IF_SOME\n\ + \ { SWAP ;\n\ + \ DIP\n\ + \ {\n\ + \ SWAP ; DIIP { DUUP } ;\n\ + \ # Checks signatures, fails if invalid\n\ + \ { DUUUP; DIP {CHECK_SIGNATURE}; SWAP; IF {DROP} \ + {FAILWITH} };\n\ + \ PUSH nat 1 ; ADD @valid } }\n\ + \ { SWAP ; DROP }\n\ + \ }\n\ + \ {\n\ + \ # There were fewer signatures in the list\n\ + \ # than keys. Not all signatures must be present, but\n\ + \ # they should be marked as absent using the option type.\n\ + \ FAIL\n\ + \ } ;\n\ + \ SWAP\n\ + \ }\n\ + \ } ;\n\ + \ # Assert that the threshold is less than or equal to the\n\ + \ # number of valid signatures.\n\ + \ ASSERT_CMPLE ;\n\ + \ DROP ; DROP ;\n\n\ + \ # Increment counter and place in storage\n\ + \ DIP { UNPAIR ; PUSH nat 1 ; ADD @new_counter ; PAIR} ;\n\n\ + \ # We have now handled the signature verification part,\n\ + \ # produce the operation requested by the signers.\n\ + \ NIL operation ; SWAP ;\n\ + \ IF_LEFT\n\ + \ { # Transfer tokens\n\ + \ UNPAIR ; UNIT ; TRANSFER_TOKENS ; CONS }\n\ + \ { IF_LEFT {\n\ + \ # Change delegate\n\ + \ SET_DELEGATE ; CONS }\n\ + \ {\n\ + \ # Change set of signatures\n\ + \ DIP { SWAP ; CAR } ; SWAP ; PAIR ; SWAP }} ;\n\ + \ PAIR }\n" + +(* Client_proto_context.originate expects the contract script as a Script.expr *) +let multisig_script : Script.expr = + Michelson_v1_parser.parse_toplevel ?check:(Some true) multisig_script_string + |> Tezos_micheline.Micheline_parser.no_parsing_error + |> function + | Error _ -> + assert false + (* This is a top level assertion, it is asserted when the client's process runs. *) + | Ok parsing_result -> + parsing_result.Michelson_v1_parser.expanded + +let multisig_script_hash = + let bytes = + Data_encoding.Binary.to_bytes_exn Script.expr_encoding multisig_script + in + Script_expr_hash.hash_bytes [bytes] + +(* The previous multisig script is the only one that the client can + originate but the client knows how to interact with several + versions of the multisig contract. For each version, the description + indicates which features are available and how to interact with + the contract. *) + +type multisig_contract_description = { + hash : Script_expr_hash.t; + (* The hash of the contract script *) + requires_chain_id : bool; + (* The signatures should contain the chain identifier *) + generic : bool; + (* False means that the contract uses a custom action type, true + means that the contract expects the action as a (lambda unit + (list operation)). *) +} + +let script_hash_of_hex_string s = + Script_expr_hash.of_bytes_exn @@ Hex.to_bytes @@ `Hex s + +(* List of known multisig contracts hashes with their kinds *) +let known_multisig_contracts : multisig_contract_description list = + let hash = multisig_script_hash in + [ {hash; requires_chain_id = true; generic = false}; + { + hash = + script_hash_of_hex_string + "36cf0b376c2d0e21f0ed42b2974fedaafdcafb9b7f8eb9254ef811b37cb46d94"; + requires_chain_id = true; + generic = false; + }; + { + hash = + script_hash_of_hex_string + "475e37a6386d0b85890eb446db1faad67f85fc814724ad07473cac8c0a124b31"; + requires_chain_id = false; + generic = false; + } ] + +let known_multisig_hashes = + List.map (fun descr -> descr.hash) known_multisig_contracts + +let check_multisig_script script : multisig_contract_description tzresult Lwt.t + = + let bytes = Data_encoding.force_bytes script in + let hash = Script_expr_hash.hash_bytes [bytes] in + match + List.find_opt + (fun d -> Script_expr_hash.(d.hash = hash)) + known_multisig_contracts + with + | None -> + fail + (Not_a_supported_multisig_contract + ( hash, + match Data_encoding.force_decode script with + | Some s -> + s + | None -> + assert false )) + | Some d -> + return d + +(* Returns [Ok ()] if [~contract] is an originated contract whose code + is [multisig_script] *) +let check_multisig_contract (cctxt : #Protocol_client_context.full) ~chain + ~block contract = + Client_proto_context.get_script cctxt ~chain ~block contract + >>=? fun script_opt -> + ( match script_opt with + | Some script -> + return script.code + | None -> + fail (Contract_has_no_script contract) ) + >>=? check_multisig_script + +let seq ~loc l = Tezos_micheline.Micheline.Seq (loc, l) + +let pair ~loc a b = + Tezos_micheline.Micheline.Prim (loc, Script.D_Pair, [a; b], []) + +let none ~loc () = Tezos_micheline.Micheline.Prim (loc, Script.D_None, [], []) + +let some ~loc a = Tezos_micheline.Micheline.Prim (loc, Script.D_Some, [a], []) + +let left ~loc a = Tezos_micheline.Micheline.Prim (loc, Script.D_Left, [a], []) + +let right ~loc b = Tezos_micheline.Micheline.Prim (loc, Script.D_Right, [b], []) + +let int ~loc i = Tezos_micheline.Micheline.Int (loc, i) + +let bytes ~loc s = Tezos_micheline.Micheline.Bytes (loc, s) + +(** * Actions *) + +type multisig_action = + | Transfer of Tez.t * Contract.t + | Change_delegate of public_key_hash option + | Change_keys of Z.t * public_key list + +let action_to_expr ~loc = function + | Transfer (amount, destination) -> + left + ~loc + (pair + ~loc + (int ~loc (Z.of_int64 (Tez.to_mutez amount))) + (bytes + ~loc + (Data_encoding.Binary.to_bytes_exn Contract.encoding destination))) + | Change_delegate delegate_opt -> + right + ~loc + (left + ~loc + ( match delegate_opt with + | None -> + none ~loc () + | Some delegate -> + some + ~loc + (bytes + ~loc + (Data_encoding.Binary.to_bytes_exn + Signature.Public_key_hash.encoding + delegate)) )) + | Change_keys (threshold, keys) -> + right + ~loc + (right + ~loc + (pair + ~loc + (int ~loc threshold) + (seq + ~loc + (List.map + (fun k -> + bytes + ~loc + (Data_encoding.Binary.to_bytes_exn + Signature.Public_key.encoding + k)) + keys)))) + +let action_of_expr e = + let fail () = + Error_monad.fail + (Action_deserialisation_error + (Tezos_micheline.Micheline.strip_locations e)) + in + match e with + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Left, + [ Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ Tezos_micheline.Micheline.Int (_, i); + Tezos_micheline.Micheline.Bytes (_, s) ], + [] ) ], + [] ) -> ( + match Tez.of_mutez (Z.to_int64 i) with + | None -> + fail () + | Some amount -> + return + @@ Transfer + (amount, Data_encoding.Binary.of_bytes_exn Contract.encoding s) ) + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Right, + [ Tezos_micheline.Micheline.Prim + ( _, + Script.D_Left, + [Tezos_micheline.Micheline.Prim (_, Script.D_None, [], [])], + [] ) ], + [] ) -> + return @@ Change_delegate None + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Right, + [ Tezos_micheline.Micheline.Prim + ( _, + Script.D_Left, + [ Tezos_micheline.Micheline.Prim + ( _, + Script.D_Some, + [Tezos_micheline.Micheline.Bytes (_, s)], + [] ) ], + [] ) ], + [] ) -> + return + @@ Change_delegate + (Some + (Data_encoding.Binary.of_bytes_exn + Signature.Public_key_hash.encoding + s)) + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Right, + [ Tezos_micheline.Micheline.Prim + ( _, + Script.D_Right, + [ Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ Tezos_micheline.Micheline.Int (_, threshold); + Tezos_micheline.Micheline.Seq (_, key_bytes) ], + [] ) ], + [] ) ], + [] ) -> + List.map_es + (function + | Tezos_micheline.Micheline.Bytes (_, s) -> + return + @@ Data_encoding.Binary.of_bytes_exn + Signature.Public_key.encoding + s + | _ -> + fail ()) + key_bytes + >>=? fun keys -> return @@ Change_keys (threshold, keys) + | _ -> + fail () + +type key_list = Signature.Public_key.t list + +(* The relevant information that we can get about a multisig smart contract *) +type multisig_contract_information = { + counter : Z.t; + threshold : Z.t; + keys : key_list; +} + +let multisig_get_information (cctxt : #Protocol_client_context.full) ~chain + ~block contract = + let open Client_proto_context in + let open Tezos_micheline.Micheline in + get_storage cctxt ~chain ~block contract + >>=? fun storage_opt -> + match storage_opt with + | None -> + fail (Contract_has_no_storage contract) + | Some storage -> ( + match root storage with + | Prim + ( _, + D_Pair, + [Int (_, counter); Int (_, threshold); Seq (_, key_nodes)], + _ ) -> + List.map_es + (function + | String (_, key_str) -> + return @@ Signature.Public_key.of_b58check_exn key_str + | _ -> + fail (Contract_has_unexpected_storage contract)) + key_nodes + >>=? fun keys -> return {counter; threshold; keys} + | _ -> + fail (Contract_has_unexpected_storage contract) ) + +let multisig_create_storage ~counter ~threshold ~keys () : + Script.expr tzresult Lwt.t = + let loc = Tezos_micheline.Micheline_parser.location_zero in + let open Tezos_micheline.Micheline in + List.map_es + (fun key -> + let key_str = Signature.Public_key.to_b58check key in + return (String (loc, key_str))) + keys + >>=? fun l -> + return @@ strip_locations + @@ pair ~loc (int ~loc counter) (pair ~loc (int ~loc threshold) (seq ~loc l)) + +(* Client_proto_context.originate expects the initial storage as a string *) +let multisig_storage_string ~counter ~threshold ~keys () = + multisig_create_storage ~counter ~threshold ~keys () + >>=? fun expr -> + return @@ Format.asprintf "%a" Michelson_v1_printer.print_expr expr + +let multisig_create_param ~counter ~action ~optional_signatures () : + Script.expr tzresult Lwt.t = + let loc = Tezos_micheline.Micheline_parser.location_zero in + let open Tezos_micheline.Micheline in + List.map_es + (fun sig_opt -> + match sig_opt with + | None -> + return @@ none ~loc () + | Some signature -> + return @@ some ~loc (String (loc, Signature.to_b58check signature))) + optional_signatures + >>=? fun l -> + return @@ strip_locations + @@ pair + ~loc + (pair ~loc (int ~loc counter) (action_to_expr ~loc action)) + (Seq (loc, l)) + +let multisig_param_string ~counter ~action ~optional_signatures () = + multisig_create_param ~counter ~action ~optional_signatures () + >>=? fun expr -> + return @@ Format.asprintf "%a" Michelson_v1_printer.print_expr expr + +let get_contract_address_maybe_chain_id ~descr ~loc ~chain_id contract = + let address = + bytes ~loc (Data_encoding.Binary.to_bytes_exn Contract.encoding contract) + in + if descr.requires_chain_id then + let chain_id_bytes = + bytes ~loc (Data_encoding.Binary.to_bytes_exn Chain_id.encoding chain_id) + in + pair ~loc chain_id_bytes address + else address + +let multisig_bytes ~counter ~action ~contract ~chain_id ~descr () = + let loc = Tezos_micheline.Micheline_parser.location_zero in + let triple = + pair + ~loc + (get_contract_address_maybe_chain_id ~descr ~loc ~chain_id contract) + (pair ~loc (int ~loc counter) (action_to_expr ~loc action)) + in + let bytes = + Data_encoding.Binary.to_bytes_exn Script.expr_encoding + @@ Tezos_micheline.Micheline.strip_locations @@ triple + in + return @@ Bytes.cat (Bytes.of_string "\005") bytes + +let check_threshold ~threshold ~keys () = + let nkeys = List.length keys in + let threshold = Z.to_int threshold in + if Compare.Int.(List.length keys < threshold) then + fail (Threshold_too_high (threshold, nkeys)) + else if Compare.Int.(threshold <= 0) then + fail (Non_positive_threshold threshold) + else return_unit + +let originate_multisig (cctxt : #Protocol_client_context.full) ~chain ~block + ?confirmations ?dry_run ?branch ?fee ?gas_limit ?storage_limit + ?verbose_signing ~delegate ~threshold ~keys ~balance ~source ~src_pk + ~src_sk ~fee_parameter () = + multisig_storage_string ~counter:Z.zero ~threshold ~keys () + >>=? fun initial_storage -> + check_threshold ~threshold ~keys () + >>=? fun () -> + Client_proto_context.originate_contract + cctxt + ~chain + ~block + ?branch + ?confirmations + ?dry_run + ?fee + ?gas_limit + ?storage_limit + ?verbose_signing + ~delegate + ~initial_storage + ~balance + ~source + ~src_pk + ~src_sk + ~code:multisig_script + ~fee_parameter + () + +type multisig_prepared_action = { + bytes : Bytes.t; + threshold : Z.t; + keys : public_key list; + counter : Z.t; +} + +let check_action ~action () = + match action with + | Change_keys (threshold, keys) -> + check_threshold ~threshold ~keys () + | _ -> + return_unit + +let prepare_multisig_transaction (cctxt : #Protocol_client_context.full) ~chain + ~block ~multisig_contract ~action () = + let contract = multisig_contract in + check_multisig_contract cctxt ~chain ~block contract + >>=? fun descr -> + check_action ~action () + >>=? fun () -> + multisig_get_information cctxt ~chain ~block contract + >>=? fun {counter; threshold; keys} -> + Chain_services.chain_id cctxt ~chain () + >>=? fun chain_id -> + multisig_bytes ~counter ~action ~contract ~descr ~chain_id () + >>=? fun bytes -> return {bytes; threshold; keys; counter} + +let check_multisig_signatures ~bytes ~threshold ~keys signatures = + let key_array = Array.of_list keys in + let nkeys = Array.length key_array in + let opt_sigs_arr = Array.make nkeys None in + let matching_key_found = ref false in + let check_signature_against_key_number signature i key = + if Signature.check key signature bytes then ( + matching_key_found := true ; + opt_sigs_arr.(i) <- Some signature ) + in + List.iter_ep + (fun signature -> + matching_key_found := false ; + List.iteri (check_signature_against_key_number signature) keys ; + fail_unless !matching_key_found (Invalid_signature signature)) + signatures + >>=? fun () -> + let opt_sigs = Array.to_list opt_sigs_arr in + let signature_count = + List.fold_left + (fun n sig_opt -> match sig_opt with Some _ -> n + 1 | None -> n) + 0 + opt_sigs + in + let threshold_int = Z.to_int threshold in + if signature_count >= threshold_int then return opt_sigs + else fail (Not_enough_signatures (threshold_int, signature_count)) + +let call_multisig (cctxt : #Protocol_client_context.full) ~chain ~block + ?confirmations ?dry_run ?verbose_signing ?branch ~source ~src_pk ~src_sk + ~multisig_contract ~action ~signatures ~amount ?fee ?gas_limit + ?storage_limit ?counter ~fee_parameter () = + prepare_multisig_transaction + cctxt + ~chain + ~block + ~multisig_contract + ~action + () + >>=? fun {bytes; threshold; keys; counter = stored_counter} -> + check_multisig_signatures ~bytes ~threshold ~keys signatures + >>=? fun optional_signatures -> + multisig_param_string ~counter:stored_counter ~action ~optional_signatures () + >>=? fun arg -> + Client_proto_context.transfer + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?branch + ~source + ~src_pk + ~src_sk + ~destination:multisig_contract + ~arg + ~amount + ?fee + ?gas_limit + ?storage_limit + ?counter + ~fee_parameter + ?verbose_signing + () + +let action_of_bytes ~multisig_contract ~stored_counter ~descr ~chain_id bytes = + if + Compare.Int.(Bytes.length bytes >= 1) + && Compare.Int.(TzEndian.get_uint8 bytes 0 = 0x05) + then + let nbytes = Bytes.sub bytes 1 (Bytes.length bytes - 1) in + match Data_encoding.Binary.of_bytes_opt Script.expr_encoding nbytes with + | None -> + fail (Bytes_deserialisation_error bytes) + | Some e -> ( + match Tezos_micheline.Micheline.root e with + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ Tezos_micheline.Micheline.Bytes (_, contract_bytes); + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [Tezos_micheline.Micheline.Int (_, counter); e], + [] ) ], + [] ) + when not descr.requires_chain_id -> + let contract = + Data_encoding.Binary.of_bytes_exn Contract.encoding contract_bytes + in + if counter = stored_counter then + if multisig_contract = contract then action_of_expr e + else fail (Bad_deserialized_contract (contract, multisig_contract)) + else fail (Bad_deserialized_counter (counter, stored_counter)) + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ Tezos_micheline.Micheline.Bytes (_, chain_id_bytes); + Tezos_micheline.Micheline.Bytes (_, contract_bytes) ], + [] ); + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [Tezos_micheline.Micheline.Int (_, counter); e], + [] ) ], + [] ) + when descr.requires_chain_id -> + let contract = + Data_encoding.Binary.of_bytes_exn Contract.encoding contract_bytes + in + let cid = + Data_encoding.Binary.of_bytes_exn Chain_id.encoding chain_id_bytes + in + if counter = stored_counter then + if multisig_contract = contract && chain_id = cid then + action_of_expr e + else fail (Bad_deserialized_contract (contract, multisig_contract)) + else fail (Bad_deserialized_counter (counter, stored_counter)) + | _ -> + fail (Bytes_deserialisation_error bytes) ) + else fail (Bytes_deserialisation_error bytes) + +let call_multisig_on_bytes (cctxt : #Protocol_client_context.full) ~chain + ~block ?confirmations ?dry_run ?verbose_signing ?branch ~source ~src_pk + ~src_sk ~multisig_contract ~bytes ~signatures ~amount ?fee ?gas_limit + ?storage_limit ?counter ~fee_parameter () = + multisig_get_information cctxt ~chain ~block multisig_contract + >>=? fun info -> + check_multisig_contract cctxt ~chain ~block multisig_contract + >>=? fun descr -> + Chain_services.chain_id cctxt ~chain () + >>=? fun chain_id -> + action_of_bytes + ~multisig_contract + ~stored_counter:info.counter + ~chain_id + ~descr + bytes + >>=? fun action -> + call_multisig + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?branch + ~source + ~src_pk + ~src_sk + ~multisig_contract + ~action + ~signatures + ~amount + ?fee + ?gas_limit + ?storage_limit + ?counter + ~fee_parameter + ?verbose_signing + () diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_multisig.mli b/src/proto_009_PsFLoren/lib_client/client_proto_multisig.mli new file mode 100644 index 0000000000000000000000000000000000000000..0e4d22dc8096f9732aae1df39c23f3ce0b905b34 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_multisig.mli @@ -0,0 +1,121 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context + +type multisig_action = + | Transfer of Tez.t * Contract.t + | Change_delegate of public_key_hash option + | Change_keys of Z.t * public_key list + +type multisig_prepared_action = { + bytes : Bytes.t; + threshold : Z.t; + keys : public_key list; + counter : Z.t; +} + +val known_multisig_hashes : Script_expr_hash.t list + +val originate_multisig : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?branch:int -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?verbose_signing:bool -> + delegate:public_key_hash option -> + threshold:Z.t -> + keys:public_key list -> + balance:Tez.t -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.origination Kind.manager Injection.result * Contract.t) tzresult Lwt.t + +val prepare_multisig_transaction : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + multisig_contract:Contract.t -> + action:multisig_action -> + unit -> + multisig_prepared_action tzresult Lwt.t + +val call_multisig : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + multisig_contract:Contract.t -> + action:multisig_action -> + signatures:Signature.t list -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Z.t -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract.t list) tzresult + Lwt.t + +val call_multisig_on_bytes : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + multisig_contract:Contract.t -> + bytes:Bytes.t -> + signatures:Signature.t list -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Z.t -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract.t list) tzresult + Lwt.t diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_programs.ml b/src/proto_009_PsFLoren/lib_client/client_proto_programs.ml new file mode 100644 index 0000000000000000000000000000000000000000..d00adc93c493346ad21266594933ea70c0028468 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_programs.ml @@ -0,0 +1,265 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline +open Michelson_v1_printer + +module Program = Client_aliases.Alias (struct + type t = Michelson_v1_parser.parsed Micheline_parser.parsing_result + + let encoding = + Data_encoding.conv + (fun ({Michelson_v1_parser.source; _}, _) -> source) + (fun source -> Michelson_v1_parser.parse_toplevel source) + Data_encoding.string + + let of_source source = return (Michelson_v1_parser.parse_toplevel source) + + let to_source ({Michelson_v1_parser.source; _}, _) = return source + + let name = "script" +end) + +let print_errors (cctxt : #Client_context.printer) errs ~show_source ~parsed = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source + ~parsed) + errs + >>= fun () -> cctxt#error "error running script" >>= fun () -> return_unit + +let print_run_result (cctxt : #Client_context.printer) ~show_source ~parsed = + function + | Ok (storage, operations, maybe_lazy_storage_diff) -> + cctxt#message + "@[@[storage@,\ + %a@]@,\ + @[emitted operations@,\ + %a@]@,\ + @[big_map diff@,\ + %a@]@]@." + print_expr + storage + (Format.pp_print_list Operation_result.pp_internal_operation) + operations + (fun ppf -> function None -> () | Some diff -> + print_big_map_diff ppf diff) + maybe_lazy_storage_diff + >>= fun () -> return_unit + | Error errs -> + print_errors cctxt errs ~show_source ~parsed + +let print_trace_result (cctxt : #Client_context.printer) ~show_source ~parsed = + function + | Ok (storage, operations, trace, maybe_lazy_storage_diff) -> + cctxt#message + "@[@[storage@,\ + %a@]@,\ + @[emitted operations@,\ + %a@]@,\ + @[big_map diff@,\ + %a@]@,\ + @[trace@,\ + %a@]@]@." + print_expr + storage + (Format.pp_print_list Operation_result.pp_internal_operation) + operations + (fun ppf -> function None -> () | Some diff -> + print_big_map_diff ppf diff) + maybe_lazy_storage_diff + print_execution_trace + trace + >>= fun () -> return_unit + | Error errs -> + print_errors cctxt errs ~show_source ~parsed + +let run (cctxt : #Protocol_client_context.rpc_context) + ~(chain : Chain_services.chain) ~block ?(amount = Tez.fifty_cents) ~balance + ~(program : Michelson_v1_parser.parsed) + ~(storage : Michelson_v1_parser.parsed) + ~(input : Michelson_v1_parser.parsed) + ~(unparsing_mode : Script_ir_translator.unparsing_mode) ?source ?payer ?gas + ?entrypoint () = + Chain_services.chain_id cctxt ~chain () + >>=? fun chain_id -> + Alpha_services.Helpers.Scripts.run_code + cctxt + (chain, block) + ?gas + ?entrypoint + ~unparsing_mode + ~script:program.expanded + ~storage:storage.expanded + ~input:input.expanded + ~amount + ~balance + ~chain_id + ~source + ~payer + +let trace (cctxt : #Protocol_client_context.rpc_context) + ~(chain : Chain_services.chain) ~block ?(amount = Tez.fifty_cents) ~balance + ~(program : Michelson_v1_parser.parsed) + ~(storage : Michelson_v1_parser.parsed) + ~(input : Michelson_v1_parser.parsed) + ~(unparsing_mode : Script_ir_translator.unparsing_mode) ?source ?payer ?gas + ?entrypoint () = + Chain_services.chain_id cctxt ~chain () + >>=? fun chain_id -> + Alpha_services.Helpers.Scripts.trace_code + cctxt + (chain, block) + ?gas + ?entrypoint + ~unparsing_mode + ~script:program.expanded + ~storage:storage.expanded + ~input:input.expanded + ~amount + ~balance + ~chain_id + ~source + ~payer + +let typecheck_data cctxt ~(chain : Chain_services.chain) ~block ?gas ?legacy + ~(data : Michelson_v1_parser.parsed) ~(ty : Michelson_v1_parser.parsed) () + = + Alpha_services.Helpers.Scripts.typecheck_data + cctxt + (chain, block) + ?gas + ?legacy + ~data:data.expanded + ~ty:ty.expanded + +let typecheck_program cctxt ~(chain : Chain_services.chain) ~block ?gas ?legacy + (program : Michelson_v1_parser.parsed) = + Alpha_services.Helpers.Scripts.typecheck_code + cctxt + (chain, block) + ?gas + ?legacy + ~script:program.expanded + +let print_typecheck_result ~emacs ~show_types ~print_source_on_error program + res (cctxt : #Client_context.printer) = + if emacs then + let (type_map, errs, _gas) = + match res with + | Ok (type_map, gas) -> + (type_map, [], Some gas) + | Error + ( Environment.Ecoproto_error + (Script_tc_errors.Ill_typed_contract (_, type_map)) + :: _ as errs ) -> + (type_map, errs, None) + | Error errs -> + ([], errs, None) + in + cctxt#message + "(@[(types . %a)@ (errors . %a)@])" + Michelson_v1_emacs.print_type_map + (program, type_map) + Michelson_v1_emacs.report_errors + (program, errs) + >>= fun () -> return_unit + else + match res with + | Ok (type_map, gas) -> + let program = Michelson_v1_printer.inject_types type_map program in + cctxt#message "@[Well typed@,Gas remaining: %a@]" Gas.pp gas + >>= fun () -> + if show_types then + cctxt#message "%a" Micheline_printer.print_expr program + >>= fun () -> return_unit + else return_unit + | Error errs -> + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:show_types + ~show_source:print_source_on_error + ~parsed:program) + errs + >>= fun () -> cctxt#error "ill-typed script" + +let entrypoint_type cctxt ~(chain : Chain_services.chain) ~block + (program : Michelson_v1_parser.parsed) ~entrypoint = + Michelson_v1_entrypoints.script_entrypoint_type + cctxt + ~chain + ~block + program.expanded + ~entrypoint + +let print_entrypoint_type (cctxt : #Client_context.printer) ~emacs ?script_name + ~show_source ~parsed ~entrypoint ty = + Michelson_v1_entrypoints.print_entrypoint_type + cctxt + ~entrypoint + ~emacs + ?script_name + ~on_errors:(print_errors cctxt ~show_source ~parsed) + ty + +let list_entrypoints cctxt ~(chain : Chain_services.chain) ~block + (program : Michelson_v1_parser.parsed) = + Michelson_v1_entrypoints.list_entrypoints + cctxt + ~chain + ~block + program.expanded + +let print_entrypoints_list (cctxt : #Client_context.printer) ~emacs + ?script_name ~show_source ~parsed ty = + Michelson_v1_entrypoints.print_entrypoints_list + cctxt + ~emacs + ?script_name + ~on_errors:(print_errors cctxt ~show_source ~parsed) + ty + +let list_unreachables cctxt ~(chain : Chain_services.chain) ~block + (program : Michelson_v1_parser.parsed) = + Michelson_v1_entrypoints.list_unreachables + cctxt + ~chain + ~block + program.expanded + +let print_unreachables (cctxt : #Client_context.printer) ~emacs ?script_name + ~show_source ~parsed ty = + Michelson_v1_entrypoints.print_unreachables + cctxt + ~emacs + ?script_name + ~on_errors:(print_errors cctxt ~show_source ~parsed) + ty diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_programs.mli b/src/proto_009_PsFLoren/lib_client/client_proto_programs.mli new file mode 100644 index 0000000000000000000000000000000000000000..f66958f9f693c107f1d17b0451965bff85799b90 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_programs.mli @@ -0,0 +1,174 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline + +module Program : + Client_aliases.Alias + with type t = Michelson_v1_parser.parsed Micheline_parser.parsing_result + +val run : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?amount:Tez.t -> + balance:Tez.t -> + program:Michelson_v1_parser.parsed -> + storage:Michelson_v1_parser.parsed -> + input:Michelson_v1_parser.parsed -> + unparsing_mode:Script_ir_translator.unparsing_mode -> + ?source:Contract.t -> + ?payer:Contract.t -> + ?gas:Gas.Arith.integral -> + ?entrypoint:string -> + unit -> + (Script.expr * packed_internal_operation list * Lazy_storage.diffs option) + tzresult + Lwt.t + +val trace : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?amount:Tez.t -> + balance:Tez.t -> + program:Michelson_v1_parser.parsed -> + storage:Michelson_v1_parser.parsed -> + input:Michelson_v1_parser.parsed -> + unparsing_mode:Script_ir_translator.unparsing_mode -> + ?source:Contract.t -> + ?payer:Contract.t -> + ?gas:Gas.Arith.integral -> + ?entrypoint:string -> + unit -> + ( Script.expr + * packed_internal_operation list + * Script_interpreter.execution_trace + * Lazy_storage.diffs option ) + tzresult + Lwt.t + +val print_run_result : + #Client_context.printer -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + ( Script_repr.expr + * packed_internal_operation list + * Lazy_storage.diffs option ) + tzresult -> + unit tzresult Lwt.t + +val print_trace_result : + #Client_context.printer -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + ( Script_repr.expr + * packed_internal_operation list + * Script_interpreter.execution_trace + * Lazy_storage.diffs option ) + tzresult -> + unit tzresult Lwt.t + +val typecheck_data : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?gas:Gas.Arith.integral -> + ?legacy:bool -> + data:Michelson_v1_parser.parsed -> + ty:Michelson_v1_parser.parsed -> + unit -> + Gas.t tzresult Lwt.t + +val typecheck_program : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?gas:Gas.Arith.integral -> + ?legacy:bool -> + Michelson_v1_parser.parsed -> + (Script_tc_errors.type_map * Gas.t) tzresult Lwt.t + +val print_typecheck_result : + emacs:bool -> + show_types:bool -> + print_source_on_error:bool -> + Michelson_v1_parser.parsed -> + (Script_tc_errors.type_map * Gas.t) tzresult -> + #Client_context.printer -> + unit tzresult Lwt.t + +val entrypoint_type : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Michelson_v1_parser.parsed -> + entrypoint:string -> + Script.expr option tzresult Lwt.t + +val print_entrypoint_type : + #Client_context.printer -> + emacs:bool -> + ?script_name:string -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + entrypoint:string -> + Script_repr.expr option tzresult -> + unit tzresult Lwt.t + +val list_entrypoints : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Michelson_v1_parser.parsed -> + (string * Script.expr) list tzresult Lwt.t + +val print_entrypoints_list : + #Client_context.printer -> + emacs:bool -> + ?script_name:string -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + (string * Script.expr) list tzresult -> + unit tzresult Lwt.t + +val list_unreachables : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Michelson_v1_parser.parsed -> + Michelson_v1_primitives.prim list list tzresult Lwt.t + +val print_unreachables : + #Client_context.printer -> + emacs:bool -> + ?script_name:string -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + Michelson_v1_primitives.prim list list tzresult -> + unit tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_utils.ml b/src/proto_009_PsFLoren/lib_client/client_proto_utils.ml new file mode 100644 index 0000000000000000000000000000000000000000..51f4f4514447cbd61fb9520a2aa0bd79aa587574 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_utils.ml @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context + +let to_json_and_bytes branch message = + let op = + ( Environment.Operation.{branch}, + Contents_list (Single (Failing_noop message)) ) + in + let encoding = Operation.unsigned_encoding in + ( Data_encoding.Json.construct encoding op, + Data_encoding.Binary.to_bytes_exn encoding op ) + +let sign_message (cctxt : #full) ~src_sk ~block ~message = + let (json, bytes) = to_json_and_bytes block message in + cctxt#message "signed content: @[%a@]" Data_encoding.Json.pp json + >>= fun () -> + Client_keys.sign cctxt ~watermark:Signature.Generic_operation src_sk bytes + +let check_message (cctxt : #full) ~block ~key_locator ~quiet ~message + ~signature = + let (json, bytes) = to_json_and_bytes block message in + ( if quiet then Lwt.return_unit + else cctxt#message "checked content: @[%a@]" Data_encoding.Json.pp json ) + >>= fun () -> + Client_keys.check + ~watermark:Signature.Generic_operation + key_locator + signature + bytes diff --git a/src/proto_009_PsFLoren/lib_client/client_proto_utils.mli b/src/proto_009_PsFLoren/lib_client/client_proto_utils.mli new file mode 100644 index 0000000000000000000000000000000000000000..c535e4b24ecb9e4eb1eb02cb16b454b9f6647112 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/client_proto_utils.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val sign_message : + #Protocol_client_context.full -> + src_sk:Client_keys.sk_uri -> + block:Block_hash.t -> + message:string -> + Signature.t tzresult Lwt.t + +val check_message : + #Protocol_client_context.full -> + block:Block_hash.t -> + key_locator:Client_keys.pk_uri -> + quiet:bool -> + message:string -> + signature:Signature.t -> + bool tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_client/dune b/src/proto_009_PsFLoren/lib_client/dune new file mode 100644 index 0000000000000000000000000000000000000000..aae0c5a55361ae490ffecac63b4d97025da5dbed --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/dune @@ -0,0 +1,26 @@ +(library + (name tezos_client_009_PsFLoren) + (public_name tezos-client-009-PsFLoren) + (libraries tezos-base + tezos-protocol-009-PsFLoren + tezos-shell-services + tezos-client-base + tezos-mockup-registration + tezos-proxy + tezos-rpc + tezos-signer-backends + tezos-protocol-009-PsFLoren-parameters + tezos-protocol-plugin-009-PsFLoren) + (library_flags (:standard -linkall)) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_protocol_009_PsFLoren + -open Tezos_protocol_plugin_009_PsFLoren + -open Tezos_protocol_009_PsFLoren_parameters + -open Tezos_rpc))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/lib_client/dune-project b/src/proto_009_PsFLoren/lib_client/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..890514c6faa1b7d3a057a6924574dbdf601ef4df --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-client-alpha) diff --git a/src/proto_009_PsFLoren/lib_client/injection.ml b/src/proto_009_PsFLoren/lib_client/injection.ml new file mode 100644 index 0000000000000000000000000000000000000000..dbc31d22b20faffc1c3f41de9261412b5d154110 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/injection.ml @@ -0,0 +1,1023 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2018 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Apply_results +open Protocol_client_context + +let get_branch (rpc_config : #Protocol_client_context.full) ~chain + ~(block : Block_services.block) branch = + let branch = Option.value ~default:0 branch in + (* TODO export parameter *) + ( match block with + | `Head n -> + return (`Head (n + branch)) + | `Hash (h, n) -> + return (`Hash (h, n + branch)) + | `Alias (a, n) -> + return (`Alias (a, n)) + | `Genesis -> + return `Genesis + | `Level i -> + return (`Level i) ) + >>=? fun block -> + Shell_services.Blocks.hash rpc_config ~chain ~block () + >>=? fun hash -> + Shell_services.Chain.chain_id rpc_config ~chain () + >>=? fun chain_id -> return (chain_id, hash) + +type 'kind preapply_result = + Operation_hash.t * 'kind operation * 'kind operation_metadata + +type 'kind result_list = + Operation_hash.t * 'kind contents_list * 'kind contents_result_list + +type 'kind result = Operation_hash.t * 'kind contents * 'kind contents_result + +type _ annotated_manager_operation = + | Manager_info : { + fee : Tez.t option; + operation : 'kind manager_operation; + gas_limit : Gas.Arith.integral option; + storage_limit : Z.t option; + } + -> 'kind annotated_manager_operation + +type packed_annotated_manager_operation = + | Annotated_manager_operation : + 'kind annotated_manager_operation + -> packed_annotated_manager_operation + +type _ annotated_manager_operation_list = + | Single_manager : + 'kind annotated_manager_operation + -> 'kind annotated_manager_operation_list + | Cons_manager : + 'kind annotated_manager_operation + * 'rest annotated_manager_operation_list + -> ('kind * 'rest) annotated_manager_operation_list + +type packed_annotated_manager_operation_list = + | Manager_list : + 'kind annotated_manager_operation_list + -> packed_annotated_manager_operation_list + +let rec manager_to_list = function + | Manager_list (Single_manager o) -> + [Annotated_manager_operation o] + | Manager_list (Cons_manager (o, os)) -> + Annotated_manager_operation o :: manager_to_list (Manager_list os) + +let rec manager_of_list = function + | [] -> + assert false + | [Annotated_manager_operation o] -> + Manager_list (Single_manager o) + | Annotated_manager_operation o :: os -> + let (Manager_list os) = manager_of_list os in + Manager_list (Cons_manager (o, os)) + +let get_manager_operation_gas_and_fee contents = + let open Operation in + let l = to_list (Contents_list contents) in + List.fold_left + (fun acc -> function + | Contents (Manager_operation {fee; gas_limit; _}) -> ( + match acc with + | Error _ as e -> + e + | Ok (total_fee, total_gas) -> ( + match Tez.(total_fee +? fee) with + | Ok total_fee -> + Ok (total_fee, Gas.Arith.add total_gas gas_limit) + | Error _ as e -> + e ) ) | _ -> acc) + (Ok (Tez.zero, Gas.Arith.zero)) + l + +type fee_parameter = { + minimal_fees : Tez.t; + minimal_nanotez_per_byte : Q.t; + minimal_nanotez_per_gas_unit : Q.t; + force_low_fee : bool; + fee_cap : Tez.t; + burn_cap : Tez.t; +} + +let dummy_fee_parameter = + { + minimal_fees = Tez.zero; + minimal_nanotez_per_byte = Q.zero; + minimal_nanotez_per_gas_unit = Q.zero; + force_low_fee = false; + fee_cap = Tez.one; + burn_cap = Tez.zero; + } + +(* Rounding up (see Z.cdiv) *) +let z_mutez_of_q_nanotez (ntz : Q.t) = + let q_mutez = Q.div ntz (Q.of_int 1000) in + Z.cdiv q_mutez.Q.num q_mutez.Q.den + +let check_fees : + type t. + #Protocol_client_context.full -> + fee_parameter -> + t contents_list -> + int -> + unit Lwt.t = + fun cctxt config op size -> + match get_manager_operation_gas_and_fee op with + | Error _ -> + assert false (* FIXME *) + | Ok (fee, gas) -> + if Tez.compare fee config.fee_cap > 0 then + cctxt#error + "The proposed fee (%s%a) are higher than the configured fee cap \ + (%s%a).@\n\ + \ Use `--fee-cap %a` to emit this operation anyway." + Client_proto_args.tez_sym + Tez.pp + fee + Client_proto_args.tez_sym + Tez.pp + config.fee_cap + Tez.pp + fee + >>= fun () -> exit 1 + else + let fees_in_nanotez = + Q.mul (Q.of_int64 (Tez.to_mutez fee)) (Q.of_int 1000) + in + let minimal_fees_in_nanotez = + Q.mul (Q.of_int64 (Tez.to_mutez config.minimal_fees)) (Q.of_int 1000) + in + let minimal_fees_for_gas_in_nanotez = + Q.mul + config.minimal_nanotez_per_gas_unit + (Q.of_bigint (Gas.Arith.integral_to_z gas)) + in + let minimal_fees_for_size_in_nanotez = + Q.mul config.minimal_nanotez_per_byte (Q.of_int size) + in + let estimated_fees_in_nanotez = + Q.add + minimal_fees_in_nanotez + (Q.add + minimal_fees_for_gas_in_nanotez + minimal_fees_for_size_in_nanotez) + in + let estimated_fees_in_mutez = + z_mutez_of_q_nanotez estimated_fees_in_nanotez + in + let estimated_fees = + match Tez.of_mutez (Z.to_int64 estimated_fees_in_mutez) with + | None -> + assert false + | Some fee -> + fee + in + if + (not config.force_low_fee) + && Q.compare fees_in_nanotez estimated_fees_in_nanotez < 0 + then + cctxt#error + "The proposed fee (%s%a) are lower than the fee that baker expect \ + by default (%s%a).@\n\ + \ Use `--force-low-fee` to emit this operation anyway." + Client_proto_args.tez_sym + Tez.pp + fee + Client_proto_args.tez_sym + Tez.pp + estimated_fees + >>= fun () -> exit 1 + else Lwt.return_unit + +let print_for_verbose_signing ppf ~watermark ~bytes ~branch ~contents = + let open Format in + pp_open_vbox ppf 0 ; + let item f = + pp_open_hovbox ppf 4 ; + pp_print_string ppf " * " ; + f ppf () ; + pp_close_box ppf () ; + pp_print_cut ppf () + in + let hash_pp l = + fprintf ppf "%s" (Base58.raw_encode Blake2B.(hash_bytes l |> to_string)) + in + item (fun ppf () -> + pp_print_text ppf "Branch: " ; + Block_hash.pp ppf branch) ; + item (fun ppf () -> + fprintf + ppf + "Watermark: `%a` (0x%s)" + Signature.pp_watermark + watermark + (Hex.of_bytes (Signature.bytes_of_watermark watermark) |> Hex.show)) ; + item (fun ppf () -> + pp_print_text ppf "Operation bytes: " ; + TzString.fold_left (* We split the bytes into lines for display: *) + (fun n c -> + pp_print_char ppf c ; + if + n < 72 + (* is the email-body standard width, ideal for copy-pasting. *) + then n + 1 + else (pp_print_space ppf () ; 0)) + 0 + (Hex.of_bytes bytes |> Hex.show) + |> ignore) ; + item (fun ppf () -> + pp_print_text ppf "Blake 2B Hash (raw): " ; + hash_pp [bytes]) ; + item (fun ppf () -> + pp_print_text + ppf + "Blake 2B Hash (ledger-style, with operation watermark): " ; + hash_pp [Signature.bytes_of_watermark watermark; bytes]) ; + let json = + Data_encoding.Json.construct + Operation.unsigned_encoding + ({branch}, Contents_list contents) + in + item (fun ppf () -> + pp_print_text ppf "JSON encoding: " ; + Data_encoding.Json.pp ppf json) ; + pp_close_box ppf () + +let preapply (type t) (cctxt : #Protocol_client_context.full) ~chain ~block + ?(verbose_signing = false) ?fee_parameter ?branch ?src_sk + (contents : t contents_list) = + get_branch cctxt ~chain ~block branch + >>=? fun (chain_id, branch) -> + let bytes = + Data_encoding.Binary.to_bytes_exn + Operation.unsigned_encoding + ({branch}, Contents_list contents) + in + ( match src_sk with + | None -> + return_none + | Some src_sk -> + let watermark = + match contents with + | Single (Endorsement _) -> + Signature.(Endorsement chain_id) + | _ -> + Signature.Generic_operation + in + ( if verbose_signing then + cctxt#message + "Pre-signature information (verbose signing):@.%t%!" + (print_for_verbose_signing ~watermark ~bytes ~branch ~contents) + else Lwt.return_unit ) + >>= fun () -> + Client_keys.sign cctxt ~watermark src_sk bytes + >>=? fun signature -> return_some signature ) + >>=? fun signature -> + let op : _ Operation.t = + {shell = {branch}; protocol_data = {contents; signature}} + in + let oph = Operation.hash op in + let size = Bytes.length bytes + Signature.size in + ( match fee_parameter with + | Some fee_parameter -> + check_fees cctxt fee_parameter contents size + | None -> + Lwt.return_unit ) + >>= fun () -> + Protocol_client_context.Alpha_block_services.Helpers.Preapply.operations + cctxt + ~chain + ~block + [Operation.pack op] + >>=? function + | [(Operation_data op', Operation_metadata result)] -> ( + match + ( Operation.equal op {shell = {branch}; protocol_data = op'}, + Apply_results.kind_equal_list contents result.contents ) + with + | (Some Operation.Eq, Some Apply_results.Eq) -> + return ((oph, op, result) : t preapply_result) + | _ -> + failwith "Unexpected result" ) + | _ -> + failwith "Unexpected result" + +let simulate (type t) (cctxt : #Protocol_client_context.full) ~chain ~block + ?branch (contents : t contents_list) = + get_branch cctxt ~chain ~block branch + >>=? fun (_chain_id, branch) -> + let op : _ Operation.t = + {shell = {branch}; protocol_data = {contents; signature = None}} + in + let oph = Operation.hash op in + Chain_services.chain_id cctxt ~chain () + >>=? fun chain_id -> + Alpha_services.Helpers.Scripts.run_operation + cctxt + (chain, block) + ~op:(Operation.pack op) + ~chain_id + >>=? function + | (Operation_data op', Operation_metadata result) -> ( + match + ( Operation.equal op {shell = {branch}; protocol_data = op'}, + Apply_results.kind_equal_list contents result.contents ) + with + | (Some Operation.Eq, Some Apply_results.Eq) -> + return ((oph, op, result) : t preapply_result) + | _ -> + failwith "Unexpected result" ) + | _ -> + failwith "Unexpected result" + +let estimated_gas_single (type kind) + (Manager_operation_result {operation_result; internal_operation_results; _} : + kind Kind.manager contents_result) = + let consumed_gas (type kind) (result : kind manager_operation_result) = + match result with + | Applied (Transaction_result {consumed_gas; _}) -> + Ok consumed_gas + | Applied (Origination_result {consumed_gas; _}) -> + Ok consumed_gas + | Applied (Reveal_result {consumed_gas}) -> + Ok consumed_gas + | Applied (Delegation_result {consumed_gas}) -> + Ok consumed_gas + | Skipped _ -> + assert false + | Backtracked (_, None) -> + Ok Gas.Arith.zero (* there must be another error for this to happen *) + | Backtracked (_, Some errs) -> + Error (Environment.wrap_tztrace errs) + | Failed (_, errs) -> + Error (Environment.wrap_tztrace errs) + in + List.fold_left + (fun acc (Internal_operation_result (_, r)) -> + acc + >>? fun acc -> consumed_gas r >>? fun gas -> Ok (Gas.Arith.add acc gas)) + (consumed_gas operation_result) + internal_operation_results + +let estimated_storage_single (type kind) origination_size + (Manager_operation_result {operation_result; internal_operation_results; _} : + kind Kind.manager contents_result) = + let storage_size_diff (type kind) (result : kind manager_operation_result) = + match result with + | Applied + (Transaction_result + {paid_storage_size_diff; allocated_destination_contract; _}) -> + if allocated_destination_contract then + Ok (Z.add paid_storage_size_diff origination_size) + else Ok paid_storage_size_diff + | Applied (Origination_result {paid_storage_size_diff; _}) -> + Ok (Z.add paid_storage_size_diff origination_size) + | Applied (Reveal_result _) -> + Ok Z.zero + | Applied (Delegation_result _) -> + Ok Z.zero + | Skipped _ -> + assert false + | Backtracked (_, None) -> + Ok Z.zero (* there must be another error for this to happen *) + | Backtracked (_, Some errs) -> + Error (Environment.wrap_tztrace errs) + | Failed (_, errs) -> + Error (Environment.wrap_tztrace errs) + in + List.fold_left + (fun acc (Internal_operation_result (_, r)) -> + acc + >>? fun acc -> + storage_size_diff r >>? fun storage -> Ok (Z.add acc storage)) + (storage_size_diff operation_result) + internal_operation_results + +let estimated_storage origination_size res = + let rec estimated_storage : type kind. kind contents_result_list -> _ = + function + | Single_result (Manager_operation_result _ as res) -> + estimated_storage_single origination_size res + | Single_result _ -> + Ok Z.zero + | Cons_result (res, rest) -> + estimated_storage_single origination_size res + >>? fun storage1 -> + estimated_storage rest >>? fun storage2 -> Ok (Z.add storage1 storage2) + in + estimated_storage res >>? fun diff -> Ok (Z.max Z.zero diff) + +let originated_contracts_single (type kind) + (Manager_operation_result {operation_result; internal_operation_results; _} : + kind Kind.manager contents_result) = + let originated_contracts (type kind) (result : kind manager_operation_result) + = + match result with + | Applied (Transaction_result {originated_contracts; _}) -> + Ok originated_contracts + | Applied (Origination_result {originated_contracts; _}) -> + Ok originated_contracts + | Applied (Reveal_result _) -> + Ok [] + | Applied (Delegation_result _) -> + Ok [] + | Skipped _ -> + assert false + | Backtracked (_, None) -> + Ok [] (* there must be another error for this to happen *) + | Backtracked (_, Some errs) -> + Error (Environment.wrap_tztrace errs) + | Failed (_, errs) -> + Error (Environment.wrap_tztrace errs) + in + List.fold_left + (fun acc (Internal_operation_result (_, r)) -> + acc + >>? fun acc -> + originated_contracts r + >>? fun contracts -> Ok (List.rev_append contracts acc)) + (originated_contracts operation_result >|? List.rev) + internal_operation_results + +let rec originated_contracts : type kind. kind contents_result_list -> _ = + function + | Single_result (Manager_operation_result _ as res) -> + originated_contracts_single res >|? List.rev + | Single_result _ -> + Ok [] + | Cons_result (res, rest) -> + originated_contracts_single res + >>? fun contracts1 -> + originated_contracts rest + >>? fun contracts2 -> Ok (List.rev_append contracts1 contracts2) + +let detect_script_failure : type kind. kind operation_metadata -> _ = + let rec detect_script_failure : type kind. kind contents_result_list -> _ = + let detect_script_failure_single (type kind) + (Manager_operation_result + {operation_result; internal_operation_results; _} : + kind Kind.manager contents_result) = + let detect_script_failure (type kind) + (result : kind manager_operation_result) = + match result with + | Applied _ -> + Ok () + | Skipped _ -> + assert false + | Backtracked (_, None) -> + (* there must be another error for this to happen *) + Ok () + | Backtracked (_, Some errs) -> + record_trace + (failure "The transfer simulation failed.") + (Error (Environment.wrap_tztrace errs)) + | Failed (_, errs) -> + record_trace + (failure "The transfer simulation failed.") + (Error (Environment.wrap_tztrace errs)) + in + List.fold_left + (fun acc (Internal_operation_result (_, r)) -> + acc >>? fun () -> detect_script_failure r) + (detect_script_failure operation_result) + internal_operation_results + in + function + | Single_result (Manager_operation_result _ as res) -> + detect_script_failure_single res + | Single_result _ -> + Ok () + | Cons_result (res, rest) -> + detect_script_failure_single res + >>? fun () -> detect_script_failure rest + in + fun {contents} -> detect_script_failure contents + +(* This value is used as a safety guard for gas limit. *) +let safety_guard = Gas.Arith.(integral_of_int_exn 100) + +let may_patch_limits (type kind) (cctxt : #Protocol_client_context.full) + ~fee_parameter ~chain ~block ?branch ?(compute_fee = false) + ~unspecified_gas_limit ~unspecified_storage_limit + (contents : kind contents_list) : kind contents_list tzresult Lwt.t = + Alpha_services.Constants.all cctxt (chain, block) + >>=? fun { parametric = + { hard_gas_limit_per_operation; + hard_storage_limit_per_operation = storage_limit; + origination_size; + cost_per_byte; + _ }; + _ } -> + let user_gas_limit_needs_patching user_gas_limit = + (unspecified_gas_limit && Gas.Arith.(user_gas_limit = zero)) + || Gas.Arith.(hard_gas_limit_per_operation <= user_gas_limit) + in + let user_storage_limit_needs_patching user_storage_limit = + unspecified_storage_limit || storage_limit <= user_storage_limit + in + let may_need_patching_single : + type kind. kind contents -> kind contents option = function + | Manager_operation c + when (compute_fee && c.fee = Tez.zero) + || user_gas_limit_needs_patching c.gas_limit + || user_storage_limit_needs_patching c.storage_limit -> + let gas_limit = + if user_gas_limit_needs_patching c.gas_limit then + hard_gas_limit_per_operation + else c.gas_limit + in + let storage_limit = + if user_storage_limit_needs_patching c.storage_limit then + storage_limit + else c.storage_limit + in + Some (Manager_operation {c with gas_limit; storage_limit}) + | _ -> + None + in + let rec may_need_patching : + type kind. kind contents_list -> kind contents_list option = function + | Single (Manager_operation _ as c) -> ( + match may_need_patching_single c with + | None -> + None + | Some op -> + Some (Single op) ) + | Single _ -> + None + | Cons ((Manager_operation _ as c), rest) -> ( + match (may_need_patching_single c, may_need_patching rest) with + | (None, None) -> + None + | (Some c, None) -> + Some (Cons (c, rest)) + | (None, Some rest) -> + Some (Cons (c, rest)) + | (Some c, Some rest) -> + Some (Cons (c, rest)) ) + in + let rec patch_fee : type kind. bool -> kind contents -> kind contents = + fun first -> function + | Manager_operation c as op -> ( + let size = + if first then + ( WithExceptions.Option.get ~loc:__LOC__ + @@ Data_encoding.Binary.fixed_length + Tezos_base.Operation.shell_header_encoding ) + + Data_encoding.Binary.length + Operation.contents_encoding + (Contents op) + + Signature.size + else + Data_encoding.Binary.length + Operation.contents_encoding + (Contents op) + in + let minimal_fees_in_nanotez = + Q.mul + (Q.of_int64 (Tez.to_mutez fee_parameter.minimal_fees)) + (Q.of_int 1000) + in + let minimal_fees_for_gas_in_nanotez = + Q.mul + fee_parameter.minimal_nanotez_per_gas_unit + (Q.of_bigint @@ Gas.Arith.integral_to_z c.gas_limit) + in + let minimal_fees_for_size_in_nanotez = + Q.mul fee_parameter.minimal_nanotez_per_byte (Q.of_int size) + in + let fees_in_nanotez = + Q.add minimal_fees_in_nanotez + @@ Q.add + minimal_fees_for_gas_in_nanotez + minimal_fees_for_size_in_nanotez + in + let fees_in_mutez = z_mutez_of_q_nanotez fees_in_nanotez in + match Tez.of_mutez (Z.to_int64 fees_in_mutez) with + | None -> + assert false + | Some fee -> + if fee <= c.fee then op + else patch_fee first (Manager_operation {c with fee}) ) + | c -> + c + in + let patch : + type kind. + bool -> + kind contents * kind contents_result -> + kind contents tzresult Lwt.t = + fun first -> function + | (Manager_operation c, (Manager_operation_result _ as result)) -> + ( if user_gas_limit_needs_patching c.gas_limit then + Lwt.return (estimated_gas_single result) + >>=? fun gas -> + if Gas.Arith.(gas = zero) then + cctxt#message "Estimated gas: none" + >>= fun () -> return Gas.Arith.zero + else + cctxt#message + "Estimated gas: %a units (will add 100 for safety)" + Gas.Arith.pp + gas + >>= fun () -> + let safe_gas = Gas.Arith.(add (ceil gas) safety_guard) in + let patched_gas = + Gas.Arith.min safe_gas hard_gas_limit_per_operation + in + return patched_gas + else return c.gas_limit ) + >>=? fun gas_limit -> + ( if c.storage_limit < Z.zero || storage_limit <= c.storage_limit then + Lwt.return + (estimated_storage_single (Z.of_int origination_size) result) + >>=? fun storage -> + if Z.equal storage Z.zero then + cctxt#message "Estimated storage: no bytes added" + >>= fun () -> return Z.zero + else + cctxt#message + "Estimated storage: %s bytes added (will add 20 for safety)" + (Z.to_string storage) + >>= fun () -> + return (Z.min (Z.add storage (Z.of_int 20)) storage_limit) + else return c.storage_limit ) + >>=? fun storage_limit -> + let cm = Manager_operation {c with gas_limit; storage_limit} in + if compute_fee && c.fee = Tez.zero then return (patch_fee first cm) + else return cm + | (c, _) -> + return c + in + let rec patch_list : + type kind. + bool -> + kind contents_and_result_list -> + kind contents_list tzresult Lwt.t = + fun first -> function + | Single_and_result + ((Manager_operation _ as op), (Manager_operation_result _ as res)) -> + patch first (op, res) >>=? fun op -> return (Single op) + | Single_and_result (op, _) -> + return (Single op) + | Cons_and_result + ((Manager_operation _ as op), (Manager_operation_result _ as res), rest) + -> + patch first (op, res) + >>=? fun op -> + patch_list false rest >>=? fun rest -> return (Cons (op, rest)) + in + match may_need_patching contents with + | Some contents -> + simulate cctxt ~chain ~block ?branch contents + >>=? fun (_, _, result) -> + ( match detect_script_failure result with + | Ok () -> + return_unit + | Error _ -> + cctxt#message + "@[This simulation failed:@,%a@]" + Operation_result.pp_operation_result + (contents, result.contents) + >>= fun () -> return_unit ) + >>=? fun () -> + Lwt.return + (estimated_storage (Z.of_int origination_size) result.contents) + >>=? (fun storage -> + Lwt.return + (Environment.wrap_tzresult + Tez.(cost_per_byte *? Z.to_int64 storage)) + >>=? fun burn -> + if Tez.(burn > fee_parameter.burn_cap) then + cctxt#error + "The operation will burn %s%a which is higher than the \ + configured burn cap (%s%a).@\n\ + \ Use `--burn-cap %a` to emit this operation." + Client_proto_args.tez_sym + Tez.pp + burn + Client_proto_args.tez_sym + Tez.pp + fee_parameter.burn_cap + Tez.pp + burn + >>= fun () -> exit 1 + else return_unit) + >>=? fun () -> + let res = pack_contents_list contents result.contents in + patch_list true res + | None -> + return contents + +let inject_operation (type kind) cctxt ~chain ~block ?confirmations + ?(dry_run = false) ?branch ?src_sk ?verbose_signing ~fee_parameter + ?compute_fee ~unspecified_gas_limit ~unspecified_storage_limit + (contents : kind contents_list) = + Tezos_client_base.Client_confirmations.wait_for_bootstrapped cctxt + >>=? fun () -> + may_patch_limits + cctxt + ~chain + ~block + ?branch + ~fee_parameter + ?compute_fee + ~unspecified_gas_limit + ~unspecified_storage_limit + contents + >>=? fun contents -> + preapply + cctxt + ~chain + ~block + ~fee_parameter + ?verbose_signing + ?branch + ?src_sk + contents + >>=? fun (_oph, op, result) -> + ( match detect_script_failure result with + | Ok () -> + return_unit + | Error _ as res -> + cctxt#message + "@[This simulation failed:@,%a@]" + Operation_result.pp_operation_result + (op.protocol_data.contents, result.contents) + >>= fun () -> Lwt.return res ) + >>=? fun () -> + let bytes = + Data_encoding.Binary.to_bytes_exn Operation.encoding (Operation.pack op) + in + if dry_run then + let oph = Operation_hash.hash_bytes [bytes] in + cctxt#message + "@[Operation: 0x%a@,Operation hash is '%a'@]" + Hex.pp + (Hex.of_bytes bytes) + Operation_hash.pp + oph + >>= fun () -> + cctxt#message + "@[Simulation result:@,%a@]" + Operation_result.pp_operation_result + (op.protocol_data.contents, result.contents) + >>= fun () -> return (oph, op.protocol_data.contents, result.contents) + else + Shell_services.Injection.operation cctxt ~chain bytes + >>=? fun oph -> + cctxt#message "Operation successfully injected in the node." + >>= fun () -> + cctxt#message "Operation hash is '%a'" Operation_hash.pp oph + >>= fun () -> + ( match confirmations with + | None -> + cctxt#message + "@[NOT waiting for the operation to be included.@,\ + Use command@,\ + \ tezos-client wait for %a to be included --confirmations 30 \ + --branch %a@,\ + and/or an external block explorer to make sure that it has been \ + included.@]" + Operation_hash.pp + oph + Block_hash.pp + op.shell.branch + >>= fun () -> return result + | Some confirmations -> ( + cctxt#message "Waiting for the operation to be included..." + >>= fun () -> + Client_confirmations.wait_for_operation_inclusion + ~branch:op.shell.branch + ~confirmations + cctxt + ~chain + oph + >>=? fun (h, i, j) -> + Alpha_block_services.Operations.operation + cctxt + ~chain + ~block:(`Hash (h, 0)) + i + j + >>=? fun op' -> + match op'.receipt with + | None -> + failwith "Internal error: pruned metadata." + | Some No_operation_metadata -> + failwith "Internal error: unexpected receipt." + | Some (Operation_metadata receipt) -> ( + match Apply_results.kind_equal_list contents receipt.contents with + | Some Apply_results.Eq -> + return (receipt : kind operation_metadata) + | None -> + failwith "Internal error: unexpected receipt." ) ) ) + >>=? fun result -> + cctxt#message + "@[This sequence of operations was run:@,%a@]" + Operation_result.pp_operation_result + (op.protocol_data.contents, result.contents) + >>= fun () -> + Lwt.return (originated_contracts result.contents) + >>=? fun contracts -> + List.iter_s + (fun c -> cctxt#message "New contract %a originated." Contract.pp c) + contracts + >>= fun () -> + ( match confirmations with + | None -> + Lwt.return_unit + | Some number -> + if number >= 30 then + cctxt#message + "The operation was included in a block %d blocks ago." + number + else + cctxt#message + "@[The operation has only been included %d blocks ago.@,\ + We recommend to wait more.@,\ + Use command@,\ + \ tezos-client wait for %a to be included --confirmations 30 \ + --branch %a@,\ + and/or an external block explorer.@]" + number + Operation_hash.pp + oph + Block_hash.pp + op.shell.branch ) + >>= fun () -> return (oph, op.protocol_data.contents, result.contents) + +let prepare_manager_operation ?fee ?gas_limit ?storage_limit operation = + Manager_info {fee; gas_limit; storage_limit; operation} + +(* [gas_limit] must correspond to + [Michelson_v1_gas.Cost_of.manager_operation] *) +let cost_of_manager_operation = Gas.Arith.integral_of_int_exn 1_000 + +let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations + ?dry_run ?verbose_signing ~source ~src_pk ~src_sk ?fee ?gas_limit + ?storage_limit ?counter ~fee_parameter (type kind) + (operations : kind annotated_manager_operation_list) : + ( Operation_hash.t + * kind Kind.manager contents_list + * kind Kind.manager contents_result_list ) + tzresult + Lwt.t = + ( match counter with + | None -> + Alpha_services.Contract.counter cctxt (chain, block) source + >>=? fun pcounter -> + let counter = Z.succ pcounter in + return counter + | Some counter -> + return counter ) + >>=? fun counter -> + Alpha_services.Contract.manager_key cctxt (chain, block) source + >>=? fun key -> + (* [is_reveal] assumes that a Reveal operation only appears as the first of a batch *) + let is_reveal : type kind. kind annotated_manager_operation_list -> bool = + function + | Single_manager (Manager_info {operation = Reveal _; _}) -> + true + | Cons_manager (Manager_info {operation = Reveal _; _}, _) -> + true + | _ -> + false + in + let (compute_fee, fee) = + match fee with None -> (true, Tez.zero) | Some fee -> (false, fee) + in + let contents_of_manager ~source ~fee ~counter ~gas_limit ~storage_limit + operation = + let (Manager_info {fee = f; gas_limit = g; storage_limit = s; operation}) = + operation + in + let fee = Option.value ~default:fee f in + let gas_limit = Option.value ~default:gas_limit g in + let storage_limit = Option.value ~default:storage_limit s in + Manager_operation + {source; fee; counter; gas_limit; storage_limit; operation} + in + let (gas_limit, unspecified_gas_limit) = + match gas_limit with + | None -> + (Gas.Arith.zero, true) + | Some gas -> + (gas, false) + in + let (storage_limit, unspecified_storage_limit) = + match storage_limit with + | None -> + (Z.zero, true) + | Some bytes -> + (bytes, false) + in + let rec build_contents : + type kind. + Z.t -> + kind annotated_manager_operation_list -> + kind Kind.manager contents_list = + fun counter -> function + | Single_manager operation -> + Single + (contents_of_manager + ~source + ~fee + ~counter + ~gas_limit + ~storage_limit + operation) + | Cons_manager (operation, rest) -> + Cons + ( contents_of_manager + ~source + ~fee + ~counter + ~gas_limit + ~storage_limit + operation, + build_contents (Z.succ counter) rest ) + in + match key with + | None when not (is_reveal operations) -> ( + let contents = + Cons + ( Manager_operation + { + source; + fee = Tez.zero; + counter; + gas_limit = cost_of_manager_operation; + storage_limit = Z.zero; + operation = Reveal src_pk; + }, + build_contents (Z.succ counter) operations ) + in + inject_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ~fee_parameter + ~compute_fee + ?verbose_signing + ?branch + ~src_sk + ~unspecified_gas_limit + ~unspecified_storage_limit:false + contents + >>=? fun (oph, op, result) -> + match pack_contents_list op result with + | Cons_and_result (_, _, rest) -> + let (op, result) = unpack_contents_list rest in + return (oph, op, result) + | _ -> + assert false ) + | Some _ when is_reveal operations -> + failwith "The manager key was previously revealed." + | _ -> + let contents = build_contents counter operations in + inject_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ~compute_fee + ~fee_parameter + ?branch + ~src_sk + ~unspecified_gas_limit + ~unspecified_storage_limit + contents diff --git a/src/proto_009_PsFLoren/lib_client/injection.mli b/src/proto_009_PsFLoren/lib_client/injection.mli new file mode 100644 index 0000000000000000000000000000000000000000..2f9bd313de4a147e58550ee99dbe669d8d927d54 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/injection.mli @@ -0,0 +1,144 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Apply_results + +type _ annotated_manager_operation = + | Manager_info : { + fee : Tez.t option; + operation : 'kind manager_operation; + gas_limit : Gas.Arith.integral option; + storage_limit : Z.t option; + } + -> 'kind annotated_manager_operation + +type packed_annotated_manager_operation = + | Annotated_manager_operation : + 'kind annotated_manager_operation + -> packed_annotated_manager_operation + +(** The [annotated_manager_operation_list] type helps making + [contents_list] from a list of [manager_operation]s. + Its construction mimics [contents_list] in order to keep + consistent types when calling [inject_manager_operation] + and [inject_operation].*) +type _ annotated_manager_operation_list = + | Single_manager : + 'kind annotated_manager_operation + -> 'kind annotated_manager_operation_list + | Cons_manager : + 'kind annotated_manager_operation + * 'rest annotated_manager_operation_list + -> ('kind * 'rest) annotated_manager_operation_list + +type packed_annotated_manager_operation_list = + | Manager_list : + 'kind annotated_manager_operation_list + -> packed_annotated_manager_operation_list + +val manager_of_list : + packed_annotated_manager_operation list -> + packed_annotated_manager_operation_list + +val manager_to_list : + packed_annotated_manager_operation_list -> + packed_annotated_manager_operation list + +type 'kind preapply_result = + Operation_hash.t * 'kind operation * 'kind operation_metadata + +type fee_parameter = { + minimal_fees : Tez.t; + minimal_nanotez_per_byte : Q.t; + minimal_nanotez_per_gas_unit : Q.t; + force_low_fee : bool; + fee_cap : Tez.t; + burn_cap : Tez.t; +} + +val dummy_fee_parameter : fee_parameter + +val preapply : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?verbose_signing:bool -> + ?fee_parameter:fee_parameter -> + ?branch:int -> + ?src_sk:Client_keys.sk_uri -> + 'kind contents_list -> + 'kind preapply_result tzresult Lwt.t + +type 'kind result_list = + Operation_hash.t * 'kind contents_list * 'kind contents_result_list + +val inject_operation : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?branch:int -> + ?src_sk:Client_keys.sk_uri -> + ?verbose_signing:bool -> + fee_parameter:fee_parameter -> + ?compute_fee:bool -> + unspecified_gas_limit:bool -> + unspecified_storage_limit:bool -> + 'kind contents_list -> + 'kind result_list tzresult Lwt.t + +type 'kind result = Operation_hash.t * 'kind contents * 'kind contents_result + +val prepare_manager_operation : + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + 'kind manager_operation -> + 'kind annotated_manager_operation + +val inject_manager_operation : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?branch:int -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + source:Signature.Public_key_hash.t -> + src_pk:Signature.public_key -> + src_sk:Client_keys.sk_uri -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Z.t -> + fee_parameter:fee_parameter -> + 'kind annotated_manager_operation_list -> + 'kind Kind.manager result_list tzresult Lwt.t + +val originated_contracts : + 'kind contents_result_list -> Contract.t list tzresult diff --git a/src/proto_009_PsFLoren/lib_client/managed_contract.ml b/src/proto_009_PsFLoren/lib_client/managed_contract.ml new file mode 100644 index 0000000000000000000000000000000000000000..0ce9aa5b240090a89addecc852939a0c03cdd226 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/managed_contract.ml @@ -0,0 +1,333 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +open Protocol +open Alpha_context +open Protocol_client_context +open Tezos_micheline + +let return_single_manager_result (oph, op, result) = + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + | _ -> + assert false + +let get_contract_manager (cctxt : #full) contract = + let open Micheline in + let open Michelson_v1_primitives in + Client_proto_context.get_storage + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + >>=? function + | None -> + cctxt#error "This is not a smart contract." + | Some storage -> ( + match root storage with + | Prim (_, D_Pair, Bytes (_, bytes) :: _, _) | Bytes (_, bytes) -> ( + match + Data_encoding.Binary.of_bytes_opt + Signature.Public_key_hash.encoding + bytes + with + | Some k -> + return k + | None -> + cctxt#error + "Cannot find a manager key in contracts storage (decoding bytes \ + failed).\n\ + Transfer from scripted contract are currently only supported for \ + \"manager\" contract." ) + | Prim (_, D_Pair, String (_, value) :: _, _) | String (_, value) -> ( + match Signature.Public_key_hash.of_b58check_opt value with + | Some k -> + return k + | None -> + cctxt#error + "Cannot find a manager key in contracts storage (\"%s\" is not a \ + valid key).\n\ + Transfer from scripted contract are currently only supported for \ + \"manager\" contract." + value ) + | _raw_storage -> + cctxt#error + "Cannot find a manager key in contracts storage (wrong storage \ + format : @[%a@]).\n\ + Transfer from scripted contract are currently only supported for \ + \"manager\" contract." + Michelson_v1_printer.print_expr + storage ) + +let parse code = + Lwt.return + ( Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression code + >>? fun exp -> + Error_monad.ok @@ Script.lazy_expr Michelson_v1_parser.(exp.expanded) ) + +let build_delegate_operation (cctxt : #full) ~chain ~block ?fee + contract (* the KT1 to delegate *) + (delegate : Signature.public_key_hash option) = + let entrypoint = "do" in + Michelson_v1_entrypoints.contract_entrypoint_type + cctxt + ~chain + ~block + ~contract + ~entrypoint + >>=? (function + | Some _ -> + (* their is a "do" entrypoint (we could check its type here)*) + let lambda = + match delegate with + | Some delegate -> + let (`Hex delegate) = + Signature.Public_key_hash.to_hex delegate + in + Format.asprintf + "{ DROP ; NIL operation ; PUSH key_hash 0x%s ; SOME ; \ + SET_DELEGATE ; CONS }" + delegate + | None -> + "{ DROP ; NIL operation ; NONE key_hash ; SET_DELEGATE ; \ + CONS }" + in + parse lambda >>=? fun param -> return (param, entrypoint) + | None -> ( + (* their is no "do" entrypoint trying "set/remove_delegate" *) + let entrypoint = + match delegate with + | Some _ -> + "set_delegate" + | None -> + "remove_delegate" + in + Michelson_v1_entrypoints.contract_entrypoint_type + cctxt + ~chain + ~block + ~contract + ~entrypoint + >>=? function + | Some _ -> + (* their is a "set/remove_delegate" entrypoint *) + let delegate_data = + match delegate with + | Some delegate -> + let (`Hex delegate) = + Signature.Public_key_hash.to_hex delegate + in + "0x" ^ delegate + | None -> + "Unit" + in + parse delegate_data + >>=? fun param -> return (param, entrypoint) + | None -> + cctxt#error + "Cannot find a %%do or %%set_delegate entrypoint in \ + contract@." )) + >>=? fun (parameters, entrypoint) -> + return + (Client_proto_context.build_transaction_operation + ~amount:Tez.zero + ~parameters + ~entrypoint + ?fee + contract) + +let set_delegate (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?branch ~fee_parameter ?fee ~source ~src_pk ~src_sk + contract (* the KT1 to delegate *) + (delegate : Signature.public_key_hash option) = + build_delegate_operation cctxt ~chain ~block ?fee contract delegate + >>=? fun operation -> + let operation = Injection.Single_manager operation in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?branch + ~source + ?fee + ~storage_limit:Z.zero + ~src_pk + ~src_sk + ~fee_parameter + operation + >>=? return_single_manager_result + +let d_unit = + Micheline.strip_locations (Prim (0, Michelson_v1_primitives.D_Unit, [], [])) + +let t_unit = + Micheline.strip_locations (Prim (0, Michelson_v1_primitives.T_unit, [], [])) + +let build_lambda_for_implicit ~delegate ~amount = + let (`Hex delegate) = Signature.Public_key_hash.to_hex delegate in + Format.asprintf + "{ DROP ; NIL operation ;PUSH key_hash 0x%s; IMPLICIT_ACCOUNT;PUSH mutez \ + %Ld ;UNIT;TRANSFER_TOKENS ; CONS }" + delegate + (Tez.to_mutez amount) + +let build_lambda_for_originated ~destination ~entrypoint ~amount + ~parameter_type ~parameter = + let destination = + Data_encoding.Binary.to_bytes_exn Contract.encoding destination + in + let amount = Tez.to_mutez amount in + let (`Hex destination) = Hex.of_bytes destination in + let entrypoint = match entrypoint with "default" -> "" | s -> "%" ^ s in + if parameter_type = t_unit then + Format.asprintf + "{ DROP ; NIL operation ;PUSH address 0x%s; CONTRACT %s %a; \ + ASSERT_SOME;PUSH mutez %Ld ;UNIT;TRANSFER_TOKENS ; CONS }" + destination + entrypoint + Michelson_v1_printer.print_expr + parameter_type + amount + else + Format.asprintf + "{ DROP ; NIL operation ;PUSH address 0x%s; CONTRACT %s %a; \ + ASSERT_SOME;PUSH mutez %Ld ;PUSH %a %a;TRANSFER_TOKENS ; CONS }" + destination + entrypoint + Michelson_v1_printer.print_expr + parameter_type + amount + Michelson_v1_printer.print_expr + parameter_type + Michelson_v1_printer.print_expr + parameter + +let build_transaction_operation (cctxt : #full) ~chain ~block ~contract + ~destination ?(entrypoint = "default") ?arg ~amount ?fee ?gas_limit + ?storage_limit () = + ( match Alpha_context.Contract.is_implicit destination with + | Some delegate when entrypoint = "default" -> + return @@ build_lambda_for_implicit ~delegate ~amount + | Some _ -> + cctxt#error + "Implicit accounts have no entrypoints. (targeted entrypoint %%%s on \ + contract %a)" + entrypoint + Contract.pp + destination + | None -> + Michelson_v1_entrypoints.contract_entrypoint_type + cctxt + ~chain + ~block + ~contract:destination + ~entrypoint + >>=? (function + | None -> + cctxt#error + "Contract %a has no entrypoint named %s" + Contract.pp + destination + entrypoint + | Some parameter_type -> + return parameter_type) + >>=? fun parameter_type -> + ( match arg with + | Some arg -> + Lwt.return @@ Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression arg + >>=? fun {expanded = arg; _} -> return_some arg + | None -> + return_none ) + >>=? fun parameter -> + let parameter = Option.value ~default:d_unit parameter in + return + @@ build_lambda_for_originated + ~destination + ~entrypoint + ~amount + ~parameter_type + ~parameter ) + >>=? fun lambda -> + parse lambda + >>=? fun parameters -> + let entrypoint = "do" in + return + (Client_proto_context.build_transaction_operation + ~amount:Tez.zero + ~parameters + ~entrypoint + ?fee + ?gas_limit + ?storage_limit + contract) + +let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?branch ~source ~src_pk ~src_sk ~contract ~destination + ?(entrypoint = "default") ?arg ~amount ?fee ?gas_limit ?storage_limit + ?counter ~fee_parameter () : + (Kind.transaction Kind.manager Injection.result * Contract.t list) tzresult + Lwt.t = + build_transaction_operation + cctxt + ~chain + ~block + ~contract + ~destination + ~entrypoint + ?arg + ~amount + ?fee + ?gas_limit + ?storage_limit + () + >>=? fun operation -> + let operation = Injection.Single_manager operation in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?branch + ~source + ?fee + ?gas_limit + ?storage_limit + ?counter + ~src_pk + ~src_sk + ~fee_parameter + operation + >>=? fun (oph, op, result) -> + Lwt.return (Injection.originated_contracts result) + >>=? fun contracts -> + return_single_manager_result (oph, op, result) + >>=? fun res -> return (res, contracts) diff --git a/src/proto_009_PsFLoren/lib_client/managed_contract.mli b/src/proto_009_PsFLoren/lib_client/managed_contract.mli new file mode 100644 index 0000000000000000000000000000000000000000..ef6d17e237a1291cc0c173f33a05529a35da9129 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/managed_contract.mli @@ -0,0 +1,111 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +open Protocol +open Alpha_context +open Protocol_client_context + +(** Retrieve the manager key in a contract storage. + The storage has to be of type `pair key_hash 'a`. +*) +val get_contract_manager : + #full -> Contract.t -> public_key_hash tzresult Lwt.t + +(** Builds a delegation operation ready for injection *) +val build_delegate_operation : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?fee:Tez.t -> + Contract.t -> + public_key_hash option -> + Kind.transaction Injection.annotated_manager_operation tzresult Lwt.t + +(** Set the delegate of a manageable contract. + For a contract with a `do`entrypoint, it builds the lambda that set + the provided delegate. + `~source` has to be the registered manager of the contract. +*) +val set_delegate : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + fee_parameter:Injection.fee_parameter -> + ?fee:Tez.t -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + Contract.t -> + public_key_hash option -> + Kind.transaction Kind.manager Injection.result tzresult Lwt.t + +(** Builds a transaction operation ready for injection *) +val build_transaction_operation : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + contract:Contract.t -> + destination:Contract.t -> + ?entrypoint:string -> + ?arg:string -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:counter -> + unit -> + Kind.transaction Injection.annotated_manager_operation tzresult Lwt.t + +(** Perform a transfer on behalf of a managed contract . + For a contract with a `do`entrypoint, it builds the lambda that + does the requested operation. + `~source` has to be the registered manager of the contract. +*) +val transfer : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + contract:Contract.t -> + destination:Contract.t -> + ?entrypoint:string -> + ?arg:string -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:counter -> + ?counter:counter -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract.t list) tzresult + Lwt.t diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_emacs.ml b/src/proto_009_PsFLoren/lib_client/michelson_v1_emacs.ml new file mode 100644 index 0000000000000000000000000000000000000000..3a1612a77f88a94a7aabc51feec3574ffa7d631d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_emacs.ml @@ -0,0 +1,239 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Tezos_micheline +open Micheline + +let print_expr ppf expr = + let print_annot ppf = function + | [] -> + () + | annots -> + Format.fprintf ppf " %s" (String.concat " " annots) + in + let rec print_expr ppf = function + | Int (_, value) -> + Format.fprintf ppf "%s" (Z.to_string value) + | String (_, value) -> + Micheline_printer.print_string ppf value + | Bytes (_, value) -> + Format.fprintf ppf "0x%a" Hex.pp (Hex.of_bytes value) + | Seq (_, items) -> + Format.fprintf + ppf + "(seq %a)" + (Format.pp_print_list ~pp_sep:Format.pp_print_space print_expr) + items + | Prim (_, name, [], []) -> + Format.fprintf ppf "%s" name + | Prim (_, name, items, annot) -> + Format.fprintf + ppf + "(%s%a%s%a)" + name + print_annot + annot + (if items = [] then "" else " ") + (Format.pp_print_list ~pp_sep:Format.pp_print_space print_expr) + items + in + let root = root (Michelson_v1_primitives.strings_of_prims expr) in + Format.fprintf ppf "@[%a@]" print_expr root + +let print_var_annots ppf = List.iter (Format.fprintf ppf "%s ") + +let print_annot_expr ppf (expr, annot) = + Format.fprintf ppf "(%a%a)" print_var_annots annot print_expr expr + +open Micheline_parser +open Script_tc_errors + +let print_type_map ppf (parsed, type_map) = + let rec print_expr_types ppf = function + | Seq (loc, []) + | Prim (loc, _, [], _) + | Int (loc, _) + | Bytes (loc, _) + | String (loc, _) -> + print_item ppf loc + | Seq (loc, items) | Prim (loc, _, items, _) -> + print_item ppf loc ; + List.iter (print_expr_types ppf) items + and print_stack ppf items = + Format.fprintf + ppf + "(%a)" + (Format.pp_print_list ~pp_sep:Format.pp_print_space print_annot_expr) + items + and print_item ppf loc = + (let ( >?? ) = Option.bind in + List.assoc loc parsed.Michelson_v1_parser.expansion_table + >?? fun ({start = {point = s; _}; stop = {point = e; _}}, locs) -> + let locs = List.sort compare locs in + List.hd locs + >?? fun hd_loc -> + List.assoc hd_loc type_map >?? fun (bef, aft) -> Some (s, e, bef, aft)) + |> Option.iter (fun (s, e, bef, aft) -> + Format.fprintf + ppf + "(@[%d %d %a %a@])@," + s + e + print_stack + bef + print_stack + aft) + in + Format.fprintf ppf "(@[%a@])" print_expr_types (root parsed.unexpanded) + +let first_error_location errs = + let rec find = function + | [] -> + 0 + | ( Inconsistent_type_annotations (loc, _, _) + | Unexpected_annotation loc + | Ill_formed_type (_, _, loc) + | Invalid_arity (loc, _, _, _) + | Invalid_seq_arity (loc, _, _) + | Invalid_namespace (loc, _, _, _) + | Invalid_primitive (loc, _, _) + | Invalid_kind (loc, _, _) + | Invalid_never_expr loc + | Fail_not_in_tail_position loc + | Undefined_binop (loc, _, _, _) + | Undefined_unop (loc, _, _) + | Bad_return (loc, _, _) + | Bad_stack (loc, _, _, _) + | Unmatched_branches (loc, _, _) + | Invalid_constant (loc, _, _) + | Invalid_syntactic_constant (loc, _, _) + | Invalid_contract (loc, _) + | Comparable_type_expected (loc, _) + | Michelson_v1_primitives.Invalid_primitive_name (_, loc) ) + :: _ -> + loc + | _ :: rest -> + find rest + in + find errs + +let report_errors ppf (parsed, errs) = + let (eco, out) = + List.fold_left + (fun (eco, out) -> function Environment.Ecoproto_error err -> + (err :: eco, out) | err -> (eco, err :: out)) + ([], []) + errs + in + let (eco, out) = (List.rev eco, List.rev out) in + Format.fprintf + ppf + "(@[%a@,%a@])" + (fun ppf errs -> + let find_location loc = + let oloc = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.assoc loc parsed.Michelson_v1_parser.unexpansion_table + in + fst + ( WithExceptions.Option.get ~loc:__LOC__ + @@ List.assoc oloc parsed.expansion_table ) + in + match errs with + | top :: errs -> + let (errs, loc) = + ( List.map (fun e -> Environment.Ecoproto_error e) (top :: errs), + match top with + | Ill_typed_contract (expr, _) | Ill_typed_data (_, expr, _) -> + if expr = parsed.expanded then + find_location (first_error_location (top :: errs)) + else find_location 0 + | Michelson_v1_primitives.Invalid_primitive_name (expr, loc) -> + if + Micheline.strip_locations + (Michelson_v1_macros.unexpand_rec (Micheline.root expr)) + = parsed.Michelson_v1_parser.unexpanded + then find_location loc + else find_location 0 + | _ -> + find_location 0 ) + in + let message = + Format.asprintf + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ~parsed) + errs + in + let {start = {point = s; _}; stop = {point = e; _}} = loc in + Format.fprintf ppf "(%d %d %S)" (s + 1) (e + 1) message + | [] -> + ()) + eco + (Format.pp_print_list (fun ppf err -> + let find_location loc = + let oloc = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.assoc loc parsed.Michelson_v1_parser.unexpansion_table + in + fst + ( WithExceptions.Option.get ~loc:__LOC__ + @@ List.assoc oloc parsed.expansion_table ) + in + let loc = + match err with + | Invalid_utf8_sequence (point, _) + | Unexpected_character (point, _) + | Undefined_escape_sequence (point, _) + | Missing_break_after_number point -> + {start = point; stop = point} + | Unterminated_string loc + | Unterminated_integer loc + | Unterminated_comment loc + | Odd_lengthed_bytes loc + | Unclosed {loc; _} + | Unexpected {loc; _} + | Extra {loc; _} -> + loc + | Misaligned node -> + location node + | _ -> + find_location 0 + in + let message = + Format.asprintf + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ~parsed) + [err] + in + let {start = {point = s; _}; stop = {point = e; _}} = loc in + Format.fprintf ppf "(%d %d %S)" (s + 1) (e + 1) message)) + out diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_emacs.mli b/src/proto_009_PsFLoren/lib_client/michelson_v1_emacs.mli new file mode 100644 index 0000000000000000000000000000000000000000..6694308d4b020319d7e4316fff8d2f07a3e5aab9 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_emacs.mli @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +val print_expr : Format.formatter -> Script.expr -> unit + +val print_type_map : + Format.formatter -> + Michelson_v1_parser.parsed * Script_tc_errors.type_map -> + unit + +val report_errors : + Format.formatter -> + Michelson_v1_parser.parsed * Error_monad.error list -> + unit diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_entrypoints.ml b/src/proto_009_PsFLoren/lib_client/michelson_v1_entrypoints.ml new file mode 100644 index 0000000000000000000000000000000000000000..2aeeb65a66524613701c5c502d572790fd0e0d61 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_entrypoints.ml @@ -0,0 +1,243 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Protocol_client_context +open Alpha_context + +type error += Contract_without_code of Contract.t + +let () = + register_error_kind + `Permanent + ~id:"contractWithoutCode" + ~title:"The given contract has no code" + ~description: + "Attempt to get the code of a contract failed because it has nocode. No \ + scriptless contract should remain." + ~pp:(fun ppf contract -> + Format.fprintf ppf "Contract has no code %a." Contract.pp contract) + Data_encoding.(obj1 (req "contract" Contract.encoding)) + (function Contract_without_code c -> Some c | _ -> None) + (fun c -> Contract_without_code c) + +let print_errors (cctxt : #Client_context.printer) errs = + cctxt#error "%a" Error_monad.pp_print_error errs >>= fun () -> return_unit + +let script_entrypoint_type cctxt ~(chain : Chain_services.chain) ~block + (program : Script.expr) ~entrypoint = + Alpha_services.Helpers.Scripts.entrypoint_type + cctxt + (chain, block) + ~script:program + ~entrypoint + >>= function + | Ok ty -> + return_some ty + | Error + (Environment.Ecoproto_error (Script_tc_errors.No_such_entrypoint _) :: _) + -> + return None + | Error _ as err -> + Lwt.return err + +let contract_entrypoint_type cctxt ~(chain : Chain_services.chain) ~block + ~contract ~entrypoint = + Alpha_services.Contract.entrypoint_type + cctxt + (chain, block) + contract + entrypoint + >>= function + | Ok ty -> + return_some ty + | Error (RPC_context.Not_found _ :: _) -> + return None + | Error _ as err -> + Lwt.return err + +let print_entrypoint_type (cctxt : #Client_context.printer) + ?(on_errors = print_errors cctxt) ~emacs ?contract ?script_name ~entrypoint + = function + | Ok (Some ty) -> + ( if emacs then + cctxt#message + "@[((entrypoint . %s) (type . %a))@]@." + entrypoint + Michelson_v1_emacs.print_expr + ty + else + cctxt#message + "@[Entrypoint %s: %a@]@." + entrypoint + Michelson_v1_printer.print_expr + ty ) + >>= fun () -> return_unit + | Ok None -> + cctxt#message + "@[No entrypoint named %s%a%a@]@." + entrypoint + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " for contract %a" Contract.pp)) + contract + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " for script %s")) + script_name + >>= fun () -> return_unit + | Error errs -> + on_errors errs + +let list_contract_unreachables_and_entrypoints cctxt ~chain ~block ~contract = + Alpha_services.Contract.list_entrypoints cctxt (chain, block) contract + +let list_contract_unreachables cctxt ~chain ~block ~contract = + list_contract_unreachables_and_entrypoints cctxt ~chain ~block ~contract + >>=? fun (unreachables, _) -> return unreachables + +let list_contract_entrypoints cctxt ~chain ~block ~contract = + list_contract_unreachables_and_entrypoints cctxt ~chain ~block ~contract + >>=? fun (_, entrypoints) -> + if not @@ List.mem_assoc "default" entrypoints then + contract_entrypoint_type + cctxt + ~chain + ~block + ~contract + ~entrypoint:"default" + >>= function + | Ok (Some ty) -> + return (("default", ty) :: entrypoints) + | Ok None -> + return entrypoints + | Error _ as err -> + Lwt.return err + else return entrypoints + +let list_unreachables cctxt ~chain ~block (program : Script.expr) = + Alpha_services.Helpers.Scripts.list_entrypoints + cctxt + (chain, block) + ~script:program + >>=? fun (unreachables, _) -> return unreachables + +let list_entrypoints cctxt ~chain ~block (program : Script.expr) = + Alpha_services.Helpers.Scripts.list_entrypoints + cctxt + (chain, block) + ~script:program + >>=? fun (_, entrypoints) -> + if not @@ List.mem_assoc "default" entrypoints then + script_entrypoint_type cctxt ~chain ~block program ~entrypoint:"default" + >>= function + | Ok (Some ty) -> + return (("default", ty) :: entrypoints) + | Ok None -> + return entrypoints + | Error _ as err -> + Lwt.return err + else return entrypoints + +let print_entrypoints_list (cctxt : #Client_context.printer) + ?(on_errors = print_errors cctxt) ~emacs ?contract ?script_name = function + | Ok entrypoint_list -> + ( if emacs then + cctxt#message + "@[(@[%a@])@." + (Format.pp_print_list + ~pp_sep:Format.pp_print_cut + (fun ppf (entrypoint, ty) -> + Format.fprintf + ppf + "@[( ( entrypoint . %s ) ( type . @[%a@]))@]" + entrypoint + Michelson_v1_emacs.print_expr + ty)) + entrypoint_list + else + cctxt#message + "@[Entrypoints%a%a: @,%a@]@." + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " for contract %a" Contract.pp)) + contract + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " for script %s")) + script_name + (Format.pp_print_list + ~pp_sep:Format.pp_print_cut + (fun ppf (entrypoint, ty) -> + Format.fprintf + ppf + "@[%s: @[%a@]@]" + entrypoint + Michelson_v1_printer.print_expr + ty)) + entrypoint_list ) + >>= fun () -> return_unit + | Error errs -> + on_errors errs + +let print_unreachables (cctxt : #Client_context.printer) + ?(on_errors = print_errors cctxt) ~emacs ?contract ?script_name = function + | Ok unreachable -> + ( if emacs then + cctxt#message + "@[(@[%a@])@." + (Format.pp_print_list ~pp_sep:Format.pp_print_cut (fun ppf path -> + Format.fprintf + ppf + "@[( unreachable-path . %a )@]" + (Format.pp_print_list + ~pp_sep:Format.pp_print_space + (fun ppf prim -> + Format.pp_print_string ppf + @@ Michelson_v1_primitives.string_of_prim prim)) + path)) + unreachable + else + match unreachable with + | [] -> + cctxt#message "@[None.@]@." + | _ -> + cctxt#message + "@[Unreachable paths in the argument%a%a: @[%a@]@." + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " of contract %a" Contract.pp)) + contract + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " of script %s")) + script_name + (Format.pp_print_list ~pp_sep:Format.pp_print_cut (fun ppf -> + Format.fprintf + ppf + "@[ %a @]" + (Format.pp_print_list + ~pp_sep:(fun ppf _ -> Format.pp_print_string ppf "/") + (fun ppf prim -> + Format.pp_print_string ppf + @@ Michelson_v1_primitives.string_of_prim prim)))) + unreachable ) + >>= fun () -> return_unit + | Error errs -> + on_errors errs diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_entrypoints.mli b/src/proto_009_PsFLoren/lib_client/michelson_v1_entrypoints.mli new file mode 100644 index 0000000000000000000000000000000000000000..96d3ad82c2f004ba7635c371029d8675efa5c60d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_entrypoints.mli @@ -0,0 +1,108 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** Returns [Some type] if the contract has an entrypoint of type [type]. None if it does not exists. *) +val script_entrypoint_type : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + Alpha_context.Script.expr -> + entrypoint:string -> + Alpha_context.Script.expr option tzresult Lwt.t + +(** Returns [Some type] if the script has an entrypoint of type [type]. None if it does not exists. *) +val contract_entrypoint_type : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + contract:Alpha_context.Contract.t -> + entrypoint:string -> + Alpha_context.Script.expr option tzresult Lwt.t + +val print_entrypoint_type : + #Client_context.printer -> + ?on_errors:(error list -> unit tzresult Lwt.t) -> + emacs:bool -> + ?contract:Alpha_context.Contract.t -> + ?script_name:string -> + entrypoint:string -> + Alpha_context.Script.expr option tzresult -> + unit tzresult Lwt.t + +(** List paths of unreachable parameters. + Only useful to test the stitching, as no such parameter should be + allowed in originated contracts. *) +val list_contract_unreachables : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + contract:Alpha_context.Contract.t -> + Michelson_v1_primitives.prim list list tzresult Lwt.t + +val list_unreachables : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + Alpha_context.Script.expr -> + Michelson_v1_primitives.prim list list tzresult Lwt.t + +val print_unreachables : + #Client_context.printer -> + ?on_errors:(error list -> unit tzresult Lwt.t) -> + emacs:bool -> + ?contract:Alpha_context.Contract.t -> + ?script_name:string -> + Michelson_v1_primitives.prim list list tzresult -> + unit tzresult Lwt.t + +(** List the contract entrypoints with their types. + If their is no explicit default, th type of default entrypoint will still be given. +*) +val list_contract_entrypoints : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + contract:Alpha_context.Contract.t -> + (string * Alpha_context.Script.expr) list tzresult Lwt.t + +(** List the script entrypoints with their types. *) +val list_entrypoints : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + Alpha_context.Script.expr -> + (string * Alpha_context.Script.expr) list tzresult Lwt.t + +(** Print the contract entrypoints with their types. *) +val print_entrypoints_list : + #Client_context.printer -> + ?on_errors:(error list -> unit tzresult Lwt.t) -> + emacs:bool -> + ?contract:Alpha_context.Contract.t -> + ?script_name:string -> + (string * Alpha_context.Script.expr) list tzresult -> + unit tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_error_reporter.ml b/src/proto_009_PsFLoren/lib_client/michelson_v1_error_reporter.ml new file mode 100644 index 0000000000000000000000000000000000000000..cf723f405df917c2c935e72cbe5fd52f11d42efc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_error_reporter.ml @@ -0,0 +1,751 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline +open Script_tc_errors +open Script_interpreter +open Michelson_v1_printer + +let print_ty ppf ty = Michelson_v1_printer.print_expr_unwrapped ppf ty + +let print_var_annot ppf annot = List.iter (Format.fprintf ppf "@ %s") annot + +let print_stack_ty ?(depth = max_int) ppf s = + let rec loop depth ppf = function + | [] -> + () + | _ when depth <= 0 -> + Format.fprintf ppf "..." + | [(last, annot)] -> + Format.fprintf ppf "%a%a" print_ty last print_var_annot annot + | (last, annot) :: rest -> + Format.fprintf + ppf + "%a%a@ :@ %a" + print_ty + last + print_var_annot + annot + (loop (depth - 1)) + rest + in + match s with + | [] -> + Format.fprintf ppf "[]" + | sty -> + Format.fprintf ppf "@[[ %a ]@]" (loop depth) sty + +let rec print_enumeration ppf = function + | [single] -> + Format.fprintf ppf "%a" Format.pp_print_text single + | [prev; last] -> + Format.fprintf + ppf + "%a@ or@ %a" + Format.pp_print_text + prev + Format.pp_print_text + last + | first :: rest -> + Format.fprintf + ppf + "%a,@ %a" + Format.pp_print_text + first + print_enumeration + rest + | [] -> + assert false + +let collect_error_locations errs = + let rec collect acc = function + | Environment.Ecoproto_error + ( Ill_formed_type (_, _, _) + | No_such_entrypoint _ + | Duplicate_entrypoint _ + | Unreachable_entrypoint _ + | Runtime_contract_error (_, _) + | Michelson_v1_primitives.Invalid_primitive_name (_, _) + | Ill_typed_data (_, _, _) + | Ill_typed_contract (_, _) ) + :: _ + | [] -> + acc + | Environment.Ecoproto_error + ( Invalid_arity (loc, _, _, _) + | Invalid_seq_arity (loc, _, _) + | Inconsistent_type_annotations (loc, _, _) + | Unexpected_annotation loc + | Ungrouped_annotations loc + | Type_too_large (loc, _, _) + | Invalid_namespace (loc, _, _, _) + | Invalid_primitive (loc, _, _) + | Invalid_kind (loc, _, _) + | Invalid_never_expr loc + | Duplicate_field (loc, _) + | Unexpected_lazy_storage loc + | Unexpected_operation loc + | Fail_not_in_tail_position loc + | Undefined_binop (loc, _, _, _) + | Undefined_unop (loc, _, _) + | Bad_return (loc, _, _) + | Bad_stack (loc, _, _, _) + | Unmatched_branches (loc, _, _) + | Self_in_lambda loc + | Invalid_constant (loc, _, _) + | Invalid_syntactic_constant (loc, _, _) + | Invalid_contract (loc, _) + | Comparable_type_expected (loc, _) + | Overflow (loc, _) + | Reject (loc, _, _) + | Pair_bad_argument loc + | Unpair_bad_argument loc + | Dup_n_bad_argument loc ) + :: rest -> + collect (loc :: acc) rest + | _ :: rest -> + collect acc rest + in + collect [] errs + +let report_errors ~details ~show_source ?parsed ppf errs = + let rec print_trace locations errs = + let print_loc ppf loc = + match locations loc with + | None -> + Format.fprintf ppf "At (unshown) location %d, " loc + | Some loc -> + Format.fprintf + ppf + "%s,@ " + (String.capitalize_ascii + (Format.asprintf "%a" Micheline_parser.print_location loc)) + in + let parsed_locations parsed loc = + let ( >?? ) = Option.bind in + List.assoc loc parsed.Michelson_v1_parser.unexpansion_table + >?? fun oloc -> + List.assoc oloc parsed.expansion_table >?? fun (ploc, _) -> Some ploc + in + let print_source ppf (parsed, _hilights) (* TODO *) = + let lines = + String.split_on_char '\n' parsed.Michelson_v1_parser.source + in + let cols = String.length (string_of_int (List.length lines)) in + Format.fprintf + ppf + "@[%a@]" + (Format.pp_print_list (fun ppf (i, l) -> + Format.fprintf ppf "%0*d: %s" cols i l)) + (List.mapi (fun i l -> (i + 1, l)) lines) + in + match errs with + | [] -> + () + | Environment.Ecoproto_error + (Michelson_v1_primitives.Invalid_primitive_name (expr, loc)) + :: rest -> + let parsed = + match parsed with + | Some parsed -> + if + Micheline.strip_locations + (Michelson_v1_macros.unexpand_rec (Micheline.root expr)) + = parsed.Michelson_v1_parser.unexpanded + then parsed + else Michelson_v1_printer.unparse_invalid expr + | None -> + Michelson_v1_printer.unparse_invalid expr + in + let hilights = loc :: collect_error_locations rest in + if show_source then + Format.fprintf + ppf + "@[@[Invalid primitive:@ %a@]@]" + print_source + (parsed, hilights) + else Format.fprintf ppf "Invalid primitive." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error (Ill_typed_data (name, expr, ty)) :: rest -> + let parsed = + match parsed with + | Some parsed when expr = parsed.Michelson_v1_parser.expanded -> + parsed + | Some _ | None -> + Michelson_v1_printer.unparse_expression expr + in + let hilights = collect_error_locations rest in + Format.fprintf + ppf + "@[@[Ill typed %adata:@ %a@]@ @[is not an \ + expression of type@ %a@]@]" + (fun ppf -> function None -> () | Some s -> + Format.fprintf ppf "%s " s) + name + print_source + (parsed, hilights) + print_ty + ty ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error (No_such_entrypoint entrypoint) :: rest -> + Format.fprintf ppf "Contract has no entrypoint named %s" entrypoint ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Duplicate_entrypoint entrypoint) :: rest -> + Format.fprintf ppf "Contract has two entrypoints named %s" entrypoint ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Unreachable_entrypoint path) :: rest -> + let path = + String.concat + "/" + (List.map Michelson_v1_primitives.string_of_prim path) + in + Format.fprintf ppf "Entrypoint at path %s is not reachable" path ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Ill_formed_type (_, expr, loc)) :: rest -> + let parsed = + match parsed with + | Some parsed when expr = parsed.Michelson_v1_parser.expanded -> + parsed + | Some _ | None -> + Michelson_v1_printer.unparse_expression expr + in + let hilights = loc :: collect_error_locations errs in + if show_source then + Format.fprintf + ppf + "@[%aill formed type:@ %a@]" + print_loc + loc + print_source + (parsed, hilights) + else Format.fprintf ppf "Ill formed type." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error (Ill_typed_contract (expr, type_map)) :: rest + -> + let parsed = + match parsed with + | Some parsed + when (not details) && expr = parsed.Michelson_v1_parser.expanded -> + parsed + | Some _ | None -> + Michelson_v1_printer.unparse_toplevel ~type_map expr + in + let hilights = collect_error_locations rest in + if show_source then + Format.fprintf + ppf + "@[Ill typed contract:@, %a@]" + print_source + (parsed, hilights) + else Format.fprintf ppf "Ill typed contract." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error Apply.Gas_quota_exceeded_init_deserialize + :: rest -> + Format.fprintf + ppf + "@[Not enough gas to deserialize the operation.@,\ + Injecting such a transaction could have you banned from mempools.@]" ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Cannot_serialize_error :: rest -> + Format.fprintf + ppf + "Error too big to serialize within the provided gas bounds." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Deprecated_instruction prim) :: rest -> + Format.fprintf + ppf + "@[Use of deprecated instruction: %s@]" + (Michelson_v1_primitives.string_of_prim prim) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Cannot_serialize_storage :: rest -> + Format.fprintf + ppf + "Cannot serialize the resulting storage value within the provided \ + gas bounds." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Missing_field prim) :: rest -> + Format.fprintf + ppf + "@[Missing contract field: %s@]" + (Michelson_v1_primitives.string_of_prim prim) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Duplicate_field (loc, prim)) :: rest -> + Format.fprintf + ppf + "@[%aduplicate contract field: %s@]" + print_loc + loc + (Michelson_v1_primitives.string_of_prim prim) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Unexpected_lazy_storage loc) :: rest -> + Format.fprintf + ppf + "%abig_map or sapling_state type not expected here" + print_loc + loc ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Unexpected_operation loc) :: rest -> + Format.fprintf + ppf + "%aoperation type forbidden in parameter, storage and constants" + print_loc + loc ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Unexpected_contract loc) :: rest -> + Format.fprintf + ppf + "%acontract type forbidden in storage and constants" + print_loc + loc ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Runtime_contract_error (contract, expr)) + :: rest -> + let parsed = + match parsed with + | Some parsed when expr = parsed.Michelson_v1_parser.expanded -> + parsed + | Some _ | None -> + Michelson_v1_printer.unparse_toplevel expr + in + let hilights = collect_error_locations rest in + Format.fprintf + ppf + "@[Runtime error in contract %a:@ %a@]" + Contract.pp + contract + print_source + (parsed, hilights) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error (Apply.Internal_operation_replay op) :: rest + -> + Format.fprintf + ppf + "@[Internal operation replay attempt:@,%a@]" + Operation_result.pp_internal_operation + op ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Gas.Gas_limit_too_high :: rest -> + Format.fprintf + ppf + "Gas limit for the operation is out of the protocol hard bounds." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Gas.Block_quota_exceeded :: rest -> + Format.fprintf + ppf + "Gas limit for the block exceeded during typechecking or execution." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Gas.Operation_quota_exceeded :: rest -> + Format.fprintf + ppf + "@[Gas limit exceeded during typechecking or execution.@,\ + Try again with a higher gas limit.@]" ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Fees.Operation_quota_exceeded :: rest -> + Format.fprintf + ppf + "@[Storage limit exceeded during typechecking or execution.@,\ + Try again with a higher storage limit.@]" ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | [Environment.Ecoproto_error (Script_interpreter.Bad_contract_parameter c)] + -> + Format.fprintf + ppf + "@[Account %a is not a smart contract, it does not take \ + arguments.@,\ + The `-arg' flag should not be used when transferring to an \ + account.@]" + Contract.pp + c + | Environment.Ecoproto_error err :: rest -> + ( match err with + | Script_interpreter.Bad_contract_parameter c -> + Format.fprintf + ppf + "Invalid argument passed to contract %a." + Contract.pp + c + | Invalid_arity (loc, name, exp, got) -> + Format.fprintf + ppf + "%aprimitive %s expects %d arguments but is given %d." + print_loc + loc + (Michelson_v1_primitives.string_of_prim name) + exp + got + | Invalid_seq_arity (loc, exp, got) -> + Format.fprintf + ppf + "%asequence expects at least %d elements but is given %d." + print_loc + loc + exp + got + | Invalid_namespace (loc, name, exp, got) -> + let human_namespace = function + | Michelson_v1_primitives.Instr_namespace -> + ("an", "instruction") + | Type_namespace -> + ("a", "type name") + | Constant_namespace -> + ("a", "constant constructor") + | Keyword_namespace -> + ("a", "keyword") + in + Format.fprintf + ppf + "@[%aunexpected %s %s, only %s %s can be used here." + print_loc + loc + (snd (human_namespace got)) + (Michelson_v1_primitives.string_of_prim name) + (fst (human_namespace exp)) + (snd (human_namespace exp)) + | Invalid_primitive (loc, exp, got) -> + Format.fprintf + ppf + "@[%ainvalid primitive %s, only %a can be used here." + print_loc + loc + (Michelson_v1_primitives.string_of_prim got) + print_enumeration + (List.map Michelson_v1_primitives.string_of_prim exp) + | Invalid_kind (loc, exp, got) -> + let human_kind = function + | Seq_kind -> + ("a", "sequence") + | Prim_kind -> + ("a", "primitive") + | Int_kind -> + ("an", "int") + | String_kind -> + ("a", "string") + | Bytes_kind -> + ("a", "byte sequence") + in + Format.fprintf + ppf + "@[%aunexpected %s, only@ %a@ can be used here." + print_loc + loc + (snd (human_kind got)) + print_enumeration + (List.map + (fun k -> + let (a, n) = human_kind k in + a ^ " " ^ n) + exp) + | Invalid_never_expr loc -> + Format.fprintf + ppf + "@[%athis expression should have type never but type never has \ + no inhabitant." + print_loc + loc + | Duplicate_map_keys (_, expr) -> + Format.fprintf + ppf + "@[Map literals cannot contain duplicate keys, however a \ + duplicate key was found:@ @[%a@]" + print_expr + expr + | Unordered_map_keys (_, expr) -> + Format.fprintf + ppf + "@[Keys in a map literal must be in strictly ascending \ + order, but they were unordered in literal:@ @[%a@]" + print_expr + expr + | Duplicate_set_values (_, expr) -> + Format.fprintf + ppf + "@[Set literals cannot contain duplicate values, however a \ + duplicate value was found:@ @[%a@]" + print_expr + expr + | Unordered_set_values (_, expr) -> + Format.fprintf + ppf + "@[Values in a set literal must be in strictly ascending \ + order, but they were unordered in literal:@ @[%a@]" + print_expr + expr + | Fail_not_in_tail_position loc -> + Format.fprintf + ppf + "%aThe FAIL instruction must appear in a tail position." + print_loc + loc + | Undefined_binop (loc, name, tya, tyb) -> + Format.fprintf + ppf + "@[@[%aoperator %s is undefined between@ %a@]@ \ + @[and@ %a.@]@]" + print_loc + loc + (Michelson_v1_primitives.string_of_prim name) + print_ty + tya + print_ty + tyb + | Undefined_unop (loc, name, ty) -> + Format.fprintf + ppf + "@[@[%aoperator %s is undefined on@ %a@]@]" + print_loc + loc + (Michelson_v1_primitives.string_of_prim name) + print_ty + ty + | Bad_return (loc, got, exp) -> + Format.fprintf + ppf + "@[%awrong stack type at end of body:@,\ + - @[expected return stack type:@ %a,@]@,\ + - @[actual stack type:@ %a.@]@]" + print_loc + loc + (fun ppf -> print_stack_ty ppf) + [(exp, [])] + (fun ppf -> print_stack_ty ppf) + got + | Bad_stack (loc, name, depth, sty) -> + Format.fprintf + ppf + "@[%awrong stack type for instruction %s:@ %a.@]" + print_loc + loc + (Michelson_v1_primitives.string_of_prim name) + (print_stack_ty ~depth) + sty + | Unmatched_branches (loc, sta, stb) -> + Format.fprintf + ppf + "@[%atwo branches don't end with the same stack type:@,\ + - @[first stack type:@ %a,@]@,\ + - @[other stack type:@ %a.@]@]" + print_loc + loc + (fun ppf -> print_stack_ty ppf) + sta + (fun ppf -> print_stack_ty ppf) + stb + | Inconsistent_annotations (annot1, annot2) -> + Format.fprintf + ppf + "@[The two annotations do not match:@,\ + - @[%s@]@,\ + - @[%s@]@]" + annot1 + annot2 + | Inconsistent_field_annotations (annot1, annot2) -> + Format.fprintf + ppf + "@[The field access annotation does not match:@,\ + - @[%s@]@,\ + - @[%s@]@]" + annot1 + annot2 + | Inconsistent_type_annotations (loc, ty1, ty2) -> + Format.fprintf + ppf + "@[%athe two types contain incompatible annotations:@,\ + - @[%a@]@,\ + - @[%a@]@]" + print_loc + loc + print_ty + ty1 + print_ty + ty2 + | Unexpected_annotation loc -> + Format.fprintf ppf "@[%aunexpected annotation." print_loc loc + | Ungrouped_annotations loc -> + Format.fprintf + ppf + "@[%aAnnotations of the same kind must be grouped." + print_loc + loc + | Type_too_large (loc, size, maximum_size) -> + Format.fprintf + ppf + "@[%atype size (%d) exceeded maximum type size (%d)." + print_loc + loc + size + maximum_size + | Pair_bad_argument loc -> + Format.fprintf + ppf + "%aPAIR expects an argument of at least 2." + print_loc + loc + | Unpair_bad_argument loc -> + Format.fprintf + ppf + "%aUNPAIR expects an argument of at least 2." + print_loc + loc + | Dup_n_bad_argument loc -> + Format.fprintf + ppf + "%aDUP n expects an argument of at least 1 (passed 0)." + print_loc + loc + | Self_in_lambda loc -> + Format.fprintf + ppf + "%aThe SELF instruction cannot appear in a lambda." + print_loc + loc + | Non_dupable_type (loc, ty) -> + Format.fprintf + ppf + "%aDUP used on the non-dupable type %a." + print_loc + loc + print_ty + ty + | Unexpected_ticket loc -> + Format.fprintf + ppf + "%aTicket in unauthorized position (type error)." + print_loc + loc + | Bad_stack_length -> + Format.fprintf ppf "Bad stack length." + | Bad_stack_item lvl -> + Format.fprintf ppf "Bad stack item %d." lvl + | Unexpected_forged_value loc -> + Format.fprintf ppf "%aUnexpected forged value." print_loc loc + | Invalid_constant (loc, got, exp) -> + Format.fprintf + ppf + "@[@[%avalue@ %a@]@ @[is invalid for type@ \ + %a.@]@]" + print_loc + loc + print_expr + got + print_ty + exp + | Invalid_syntactic_constant (loc, got, exp) -> + Format.fprintf + ppf + "@[@[%avalue@ %a@]@ @[is invalid, \ + expected@ %s@]@]" + print_loc + loc + print_expr + got + exp + | Invalid_contract (loc, contract) -> + Format.fprintf + ppf + "%ainvalid contract %a." + print_loc + loc + Contract.pp + contract + | Comparable_type_expected (loc, ty) -> + Format.fprintf ppf "%acomparable type expected." print_loc loc ; + Format.fprintf + ppf + "@[@[Type@ %a@]@ is not comparable.@]" + print_ty + ty + | Inconsistent_types (tya, tyb) -> + Format.fprintf + ppf + "@[@[Type@ %a@]@ @[is not compatible with \ + type@ %a.@]@]" + print_ty + tya + print_ty + tyb + | Reject (loc, v, trace) -> + Format.fprintf + ppf + "%ascript reached FAILWITH instruction@ @[with@ %a@]%a" + print_loc + loc + print_expr + v + (fun ppf -> function None -> () | Some trace -> + Format.fprintf + ppf + "@,@[trace@,%a@]" + print_execution_trace + trace) + trace + | Overflow (loc, trace) -> + Format.fprintf + ppf + "%aunexpected arithmetic overflow%a" + print_loc + loc + (fun ppf -> function None -> () | Some trace -> + Format.fprintf + ppf + "@,@[trace@,%a@]" + print_execution_trace + trace) + trace + | err -> + Format.fprintf ppf "%a" Environment.Error_monad.pp err ) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | err :: rest -> + Format.fprintf ppf "%a" Error_monad.pp err ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + in + Format.fprintf ppf "@[" ; + print_trace (fun _ -> None) errs ; + Format.fprintf ppf "@]" diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_error_reporter.mli b/src/proto_009_PsFLoren/lib_client/michelson_v1_error_reporter.mli new file mode 100644 index 0000000000000000000000000000000000000000..e1bbea6eb12cea8b035809cb0a27c7bc592adc74 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_error_reporter.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val report_errors : + details:bool -> + show_source:bool -> + ?parsed:Michelson_v1_parser.parsed -> + Format.formatter -> + Error_monad.error list -> + unit diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_macros.ml b/src/proto_009_PsFLoren/lib_client/michelson_v1_macros.ml new file mode 100644 index 0000000000000000000000000000000000000000..532af9d04b20c77a20069c64837b31fea2cdba38 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_macros.ml @@ -0,0 +1,1543 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Tezos_micheline +open Micheline +module IntMap = Map.Make (Compare.Int) + +type 'l node = ('l, string) Micheline.node + +type error += Unexpected_macro_annotation of string + +type error += Sequence_expected of string + +type error += Invalid_arity of string * int * int + +let rec check_letters str i j f = + i > j || (f str.[i] && check_letters str (i + 1) j f) + +let expand_caddadr original = + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len > 3 + && str.[0] = 'C' + && str.[len - 1] = 'R' + && check_letters str 1 (len - 2) (function + | 'A' | 'D' -> + true + | _ -> + false) + then + ( match args with + | [] -> + ok () + | _ :: _ -> + error (Invalid_arity (str, List.length args, 0)) ) + >>? fun () -> + let path_annot = + List.filter (function "@%" | "@%%" -> true | _ -> false) annot + in + let rec parse i acc = + if i = 0 then Seq (loc, acc) + else + let annot = if i = len - 2 then annot else path_annot in + match str.[i] with + | 'A' -> + parse (i - 1) (Prim (loc, "CAR", [], annot) :: acc) + | 'D' -> + parse (i - 1) (Prim (loc, "CDR", [], annot) :: acc) + | _ -> + assert false + in + ok (Some (parse (len - 2) [])) + else ok None + | _ -> + ok None + +let expand_carn original = + match original with + | Prim (loc, "CAR", [Int (loc2, n)], annot) -> + ok + (Some + (Seq + ( loc, + [ Prim + ( loc, + "GET", + [Int (loc2, Z.(of_int 1 + (n * of_int 2)))], + annot ) ] ))) + | _ -> + ok None + +let expand_cdrn original = + match original with + | Prim (loc, "CDR", [Int (loc2, n)], annot) -> + ok + (Some + (Seq + (loc, [Prim (loc, "GET", [Int (loc2, Z.(n * of_int 2))], annot)]))) + | _ -> + ok None + +let extract_field_annots annot = + List.partition + (fun a -> + match a.[0] with + | '%' -> + true + | _ -> + false + | exception Invalid_argument _ -> + false) + annot + +let expand_set_caddadr original = + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len >= 7 + && String.sub str 0 5 = "SET_C" + && str.[len - 1] = 'R' + && check_letters str 5 (len - 2) (function + | 'A' | 'D' -> + true + | _ -> + false) + then + ( match args with + | [] -> + ok () + | _ :: _ -> + error (Invalid_arity (str, List.length args, 0)) ) + >>? fun () -> + ( match extract_field_annots annot with + | ([], annot) -> + ok (None, annot) + | ([f], annot) -> + ok (Some f, annot) + | (_, _) -> + error (Unexpected_macro_annotation str) ) + >>? fun (field_annot, annot) -> + let rec parse i acc = + if i = 4 then acc + else + let annot = if i = 5 then annot else [] in + match str.[i] with + | 'A' -> + let acc = + Seq + ( loc, + [ Prim (loc, "DUP", [], []); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CAR", [], ["@%%"]); acc])], + [] ); + Prim (loc, "CDR", [], ["@%%"]); + Prim (loc, "SWAP", [], []); + Prim (loc, "PAIR", [], "%@" :: "%@" :: annot) ] ) + in + parse (i - 1) acc + | 'D' -> + let acc = + Seq + ( loc, + [ Prim (loc, "DUP", [], []); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CDR", [], ["@%%"]); acc])], + [] ); + Prim (loc, "CAR", [], ["@%%"]); + Prim (loc, "PAIR", [], "%@" :: "%@" :: annot) ] ) + in + parse (i - 1) acc + | _ -> + assert false + in + match str.[len - 2] with + | 'A' -> + let access_check = + match field_annot with + | None -> + [] + | Some f -> + [ Prim (loc, "DUP", [], []); + Prim (loc, "CAR", [], [f]); + Prim (loc, "DROP", [], []) ] + in + let encoding = + [Prim (loc, "CDR", [], ["@%%"]); Prim (loc, "SWAP", [], [])] + in + let pair = + [ Prim + ( loc, + "PAIR", + [], + [Option.value field_annot ~default:"%"; "%@"] ) ] + in + let init = Seq (loc, access_check @ encoding @ pair) in + ok (Some (parse (len - 3) init)) + | 'D' -> + let access_check = + match field_annot with + | None -> + [] + | Some f -> + [ Prim (loc, "DUP", [], []); + Prim (loc, "CDR", [], [f]); + Prim (loc, "DROP", [], []) ] + in + let encoding = [Prim (loc, "CAR", [], ["@%%"])] in + let pair = + [ Prim + ( loc, + "PAIR", + [], + ["%@"; Option.value field_annot ~default:"%"] ) ] + in + let init = Seq (loc, access_check @ encoding @ pair) in + ok (Some (parse (len - 3) init)) + | _ -> + assert false + else ok None + | _ -> + ok None + +let expand_map_caddadr original = + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len >= 7 + && String.sub str 0 5 = "MAP_C" + && str.[len - 1] = 'R' + && check_letters str 5 (len - 2) (function + | 'A' | 'D' -> + true + | _ -> + false) + then + ( match args with + | [(Seq _ as code)] -> + ok code + | [_] -> + error (Sequence_expected str) + | [] | _ :: _ :: _ -> + error (Invalid_arity (str, List.length args, 1)) ) + >>? fun code -> + ( match extract_field_annots annot with + | ([], annot) -> + ok (None, annot) + | ([f], annot) -> + ok (Some f, annot) + | (_, _) -> + error (Unexpected_macro_annotation str) ) + >>? fun (field_annot, annot) -> + let rec parse i acc = + if i = 4 then acc + else + let annot = if i = 5 then annot else [] in + match str.[i] with + | 'A' -> + let acc = + Seq + ( loc, + [ Prim (loc, "DUP", [], []); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CAR", [], ["@%%"]); acc])], + [] ); + Prim (loc, "CDR", [], ["@%%"]); + Prim (loc, "SWAP", [], []); + Prim (loc, "PAIR", [], "%@" :: "%@" :: annot) ] ) + in + parse (i - 1) acc + | 'D' -> + let acc = + Seq + ( loc, + [ Prim (loc, "DUP", [], []); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CDR", [], ["@%%"]); acc])], + [] ); + Prim (loc, "CAR", [], ["@%%"]); + Prim (loc, "PAIR", [], "%@" :: "%@" :: annot) ] ) + in + parse (i - 1) acc + | _ -> + assert false + in + let cr_annot = + match field_annot with + | None -> + [] + | Some f -> + ["@" ^ String.sub f 1 (String.length f - 1)] + in + match str.[len - 2] with + | 'A' -> + let init = + Seq + ( loc, + [ Prim (loc, "DUP", [], []); + Prim (loc, "CDR", [], ["@%%"]); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CAR", [], cr_annot); code])], + [] ); + Prim (loc, "SWAP", [], []); + Prim + ( loc, + "PAIR", + [], + [Option.value field_annot ~default:"%"; "%@"] ) ] ) + in + ok (Some (parse (len - 3) init)) + | 'D' -> + let init = + Seq + ( loc, + [ Prim (loc, "DUP", [], []); + Prim (loc, "CDR", [], cr_annot); + code; + Prim (loc, "SWAP", [], []); + Prim (loc, "CAR", [], ["@%%"]); + Prim + ( loc, + "PAIR", + [], + ["%@"; Option.value field_annot ~default:"%"] ) ] ) + in + ok (Some (parse (len - 3) init)) + | _ -> + assert false + else ok None + | _ -> + ok None + +exception Not_a_roman + +let decimal_of_roman roman = + (* http://rosettacode.org/wiki/Roman_numerals/Decode#OCaml *) + let arabic = ref 0 in + let lastval = ref 0 in + for i = String.length roman - 1 downto 0 do + let n = + match roman.[i] with + | 'M' -> + 1000 + | 'D' -> + 500 + | 'C' -> + 100 + | 'L' -> + 50 + | 'X' -> + 10 + | 'V' -> + 5 + | 'I' -> + 1 + | _ -> + raise_notrace Not_a_roman + in + if Compare.Int.(n < !lastval) then arabic := !arabic - n + else arabic := !arabic + n ; + lastval := n + done ; + !arabic + +let dip ~loc ?(annot = []) depth instr = + assert (depth >= 0) ; + if depth = 1 then Prim (loc, "DIP", [instr], annot) + else Prim (loc, "DIP", [Int (loc, Z.of_int depth); instr], annot) + +let expand_deprecated_dxiiivp original = + (* transparently expands deprecated macro [DI...IP] to instruction [DIP n] *) + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if len > 3 && str.[0] = 'D' && str.[len - 1] = 'P' then + try + let depth = decimal_of_roman (String.sub str 1 (len - 2)) in + match args with + | [(Seq (_, _) as arg)] -> + ok @@ Some (dip ~loc ~annot depth arg) + | [_] -> + error (Sequence_expected str) + | [] | _ :: _ :: _ -> + error (Invalid_arity (str, List.length args, 1)) + with Not_a_roman -> ok None + else ok None + | _ -> + ok None + +exception Not_a_pair + +type pair_item = A | I | P of int * pair_item * pair_item + +let parse_pair_substr str ~len start = + let rec parse ?left i = + if i = len - 1 then raise_notrace Not_a_pair + else if str.[i] = 'P' then + let (next_i, l) = parse ~left:true (i + 1) in + let (next_i, r) = parse ~left:false next_i in + (next_i, P (i, l, r)) + else if str.[i] = 'A' && left = Some true then (i + 1, A) + else if str.[i] = 'I' && left <> Some true then (i + 1, I) + else raise_notrace Not_a_pair + in + let (last, ast) = parse start in + if last <> len - 1 then raise_notrace Not_a_pair else ast + +let unparse_pair_item ast = + let rec unparse ast acc = + match ast with + | P (_, l, r) -> + unparse r (unparse l ("P" :: acc)) + | A -> + "A" :: acc + | I -> + "I" :: acc + in + List.rev ("R" :: unparse ast []) |> String.concat "" + +let pappaiir_annots_pos ast annot = + let rec find_annots_pos p_pos ast annots acc = + match (ast, annots) with + | (_, []) -> + (annots, acc) + | (P (i, left, right), _) -> + let (annots, acc) = find_annots_pos i left annots acc in + find_annots_pos i right annots acc + | (A, a :: annots) -> + let pos = + match IntMap.find p_pos acc with + | None -> + ([a], []) + | Some (_, cdr) -> + ([a], cdr) + in + (annots, IntMap.add p_pos pos acc) + | (I, a :: annots) -> + let pos = + match IntMap.find p_pos acc with + | None -> + ([], [a]) + | Some (car, _) -> + (car, [a]) + in + (annots, IntMap.add p_pos pos acc) + in + snd (find_annots_pos 0 ast annot IntMap.empty) + +let expand_pappaiir original = + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len > 4 + && str.[0] = 'P' + && str.[len - 1] = 'R' + && check_letters str 1 (len - 2) (function + | 'P' | 'A' | 'I' -> + true + | _ -> + false) + then + try + let (field_annots, annot) = extract_field_annots annot in + let ast = parse_pair_substr str ~len 0 in + let field_annots_pos = pappaiir_annots_pos ast field_annots in + let rec parse p (depth, acc) = + match p with + | P (i, left, right) -> + let annot = + match (i, IntMap.find i field_annots_pos) with + | (0, None) -> + annot + | (_, None) -> + [] + | (0, Some ([], cdr_annot)) -> + ("%" :: cdr_annot) @ annot + | (_, Some ([], cdr_annot)) -> + "%" :: cdr_annot + | (0, Some (car_annot, cdr_annot)) -> + car_annot @ cdr_annot @ annot + | (_, Some (car_annot, cdr_annot)) -> + car_annot @ cdr_annot + in + let acc = + if depth = 0 then Prim (loc, "PAIR", [], annot) :: acc + else + dip ~loc depth (Seq (loc, [Prim (loc, "PAIR", [], annot)])) + :: acc + in + (depth, acc) |> parse left |> parse right + | A | I -> + (depth + 1, acc) + in + let (_, expanded) = parse ast (0, []) in + ( match args with + | [] -> + ok () + | _ :: _ -> + error (Invalid_arity (str, List.length args, 0)) ) + >>? fun () -> ok (Some (Seq (loc, expanded))) + with Not_a_pair -> ok None + else ok None + | _ -> + ok None + +let expand_unpappaiir original = + match original with + | Prim (loc, str, args, _annot) -> + let len = String.length str in + if + len > 6 + && String.sub str 0 3 = "UNP" + && str.[len - 1] = 'R' + && check_letters str 3 (len - 2) (function + | 'P' | 'A' | 'I' -> + true + | _ -> + false) + then + try + let unpair = Prim (loc, "UNPAIR", [], []) in + let ast = parse_pair_substr str ~len 2 in + let rec parse p (depth, acc) = + match p with + | P (_i, left, right) -> + let acc = + if depth = 0 then unpair :: acc + else dip ~loc depth (Seq (loc, [unpair])) :: acc + in + (depth, acc) |> parse left |> parse right + | A | I -> + (depth + 1, acc) + in + let (_, rev_expanded) = parse ast (0, []) in + let expanded = Seq (loc, List.rev rev_expanded) in + ( match args with + | [] -> + ok () + | _ :: _ -> + error (Invalid_arity (str, List.length args, 0)) ) + >>? fun () -> ok (Some expanded) + with Not_a_pair -> ok None + else ok None + | _ -> + ok None + +exception Not_a_dup + +let expand_deprecated_duuuuup original = + (* transparently expands deprecated macro [DU...UP] to [{ DUP n }] *) + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len > 3 + && str.[0] = 'D' + && str.[len - 1] = 'P' + && check_letters str 1 (len - 2) (( = ) 'U') + then + ( match args with + | [] -> + ok () + | _ :: _ -> + error (Invalid_arity (str, List.length args, 0)) ) + >>? fun () -> + try + let rec parse i = + if i = 1 then + Prim (loc, "DUP", [Int (loc, Z.of_int (len - 2))], annot) + else if str.[i] = 'U' then parse (i - 1) + else raise_notrace Not_a_dup + in + ok (Some (parse (len - 2))) + with Not_a_dup -> ok None + else ok None + | _ -> + ok None + +let expand_compare original = + let cmp loc is annot = + let is = + match List.rev_map (fun i -> Prim (loc, i, [], [])) is with + | Prim (loc, i, args, _) :: r -> + List.rev (Prim (loc, i, args, annot) :: r) + | is -> + List.rev is + in + ok (Some (Seq (loc, is))) + in + let ifcmp loc is l r annot = + let is = + List.map (fun i -> Prim (loc, i, [], [])) is + @ [Prim (loc, "IF", [l; r], annot)] + in + ok (Some (Seq (loc, is))) + in + match original with + | Prim (loc, "CMPEQ", [], annot) -> + cmp loc ["COMPARE"; "EQ"] annot + | Prim (loc, "CMPNEQ", [], annot) -> + cmp loc ["COMPARE"; "NEQ"] annot + | Prim (loc, "CMPLT", [], annot) -> + cmp loc ["COMPARE"; "LT"] annot + | Prim (loc, "CMPGT", [], annot) -> + cmp loc ["COMPARE"; "GT"] annot + | Prim (loc, "CMPLE", [], annot) -> + cmp loc ["COMPARE"; "LE"] annot + | Prim (loc, "CMPGE", [], annot) -> + cmp loc ["COMPARE"; "GE"] annot + | Prim + ( _, + (("CMPEQ" | "CMPNEQ" | "CMPLT" | "CMPGT" | "CMPLE" | "CMPGE") as str), + args, + [] ) -> + error (Invalid_arity (str, List.length args, 0)) + | Prim (loc, "IFCMPEQ", [l; r], annot) -> + ifcmp loc ["COMPARE"; "EQ"] l r annot + | Prim (loc, "IFCMPNEQ", [l; r], annot) -> + ifcmp loc ["COMPARE"; "NEQ"] l r annot + | Prim (loc, "IFCMPLT", [l; r], annot) -> + ifcmp loc ["COMPARE"; "LT"] l r annot + | Prim (loc, "IFCMPGT", [l; r], annot) -> + ifcmp loc ["COMPARE"; "GT"] l r annot + | Prim (loc, "IFCMPLE", [l; r], annot) -> + ifcmp loc ["COMPARE"; "LE"] l r annot + | Prim (loc, "IFCMPGE", [l; r], annot) -> + ifcmp loc ["COMPARE"; "GE"] l r annot + | Prim (loc, "IFEQ", [l; r], annot) -> + ifcmp loc ["EQ"] l r annot + | Prim (loc, "IFNEQ", [l; r], annot) -> + ifcmp loc ["NEQ"] l r annot + | Prim (loc, "IFLT", [l; r], annot) -> + ifcmp loc ["LT"] l r annot + | Prim (loc, "IFGT", [l; r], annot) -> + ifcmp loc ["GT"] l r annot + | Prim (loc, "IFLE", [l; r], annot) -> + ifcmp loc ["LE"] l r annot + | Prim (loc, "IFGE", [l; r], annot) -> + ifcmp loc ["GE"] l r annot + | Prim + ( _, + ( ( "IFCMPEQ" + | "IFCMPNEQ" + | "IFCMPLT" + | "IFCMPGT" + | "IFCMPLE" + | "IFCMPGE" + | "IFEQ" + | "IFNEQ" + | "IFLT" + | "IFGT" + | "IFLE" + | "IFGE" ) as str ), + args, + [] ) -> + error (Invalid_arity (str, List.length args, 2)) + | Prim + ( _, + ( ( "IFCMPEQ" + | "IFCMPNEQ" + | "IFCMPLT" + | "IFCMPGT" + | "IFCMPLE" + | "IFCMPGE" + | "IFEQ" + | "IFNEQ" + | "IFLT" + | "IFGT" + | "IFLE" + | "IFGE" ) as str ), + [], + _ :: _ ) -> + error (Unexpected_macro_annotation str) + | _ -> + ok None + +let expand_asserts original = + let may_rename loc = function + | [] -> + Seq (loc, []) + | annot -> + Seq (loc, [Prim (loc, "RENAME", [], annot)]) + in + let fail_false ?(annot = []) loc = + [may_rename loc annot; Seq (loc, [Prim (loc, "FAIL", [], [])])] + in + let fail_true ?(annot = []) loc = + [Seq (loc, [Prim (loc, "FAIL", [], [])]); may_rename loc annot] + in + match original with + | Prim (loc, "ASSERT", [], []) -> + ok @@ Some (Seq (loc, [Prim (loc, "IF", fail_false loc, [])])) + | Prim (loc, "ASSERT_NONE", [], []) -> + ok @@ Some (Seq (loc, [Prim (loc, "IF_NONE", fail_false loc, [])])) + | Prim (loc, "ASSERT_SOME", [], annot) -> + ok @@ Some (Seq (loc, [Prim (loc, "IF_NONE", fail_true ~annot loc, [])])) + | Prim (loc, "ASSERT_LEFT", [], annot) -> + ok + @@ Some (Seq (loc, [Prim (loc, "IF_LEFT", fail_false ~annot loc, [])])) + | Prim (loc, "ASSERT_RIGHT", [], annot) -> + ok @@ Some (Seq (loc, [Prim (loc, "IF_LEFT", fail_true ~annot loc, [])])) + | Prim + ( _, + ( ( "ASSERT" + | "ASSERT_NONE" + | "ASSERT_SOME" + | "ASSERT_LEFT" + | "ASSERT_RIGHT" ) as str ), + args, + [] ) -> + error (Invalid_arity (str, List.length args, 0)) + | Prim (_, (("ASSERT" | "ASSERT_NONE") as str), [], _ :: _) -> + error (Unexpected_macro_annotation str) + | Prim (loc, s, args, annot) + when String.(length s > 7 && equal (sub s 0 7) "ASSERT_") -> ( + ( match args with + | [] -> + ok () + | _ :: _ -> + error (Invalid_arity (s, List.length args, 0)) ) + >>? fun () -> + ( match annot with + | _ :: _ -> + error (Unexpected_macro_annotation s) + | [] -> + ok () ) + >>? fun () -> + let remaining = String.(sub s 7 (length s - 7)) in + let remaining_prim = Prim (loc, remaining, [], []) in + match remaining with + | "EQ" | "NEQ" | "LT" | "LE" | "GE" | "GT" -> + ok + @@ Some + (Seq + (loc, [remaining_prim; Prim (loc, "IF", fail_false loc, [])])) + | _ -> ( + expand_compare remaining_prim + >|? function + | None -> + None + | Some seq -> + Some (Seq (loc, [seq; Prim (loc, "IF", fail_false loc, [])])) ) ) + | _ -> + ok None + +let expand_if_some = function + | Prim (loc, "IF_SOME", [right; left], annot) -> + ok @@ Some (Seq (loc, [Prim (loc, "IF_NONE", [left; right], annot)])) + | Prim (_, "IF_SOME", args, _annot) -> + error (Invalid_arity ("IF_SOME", List.length args, 2)) + | _ -> + ok @@ None + +let expand_if_right = function + | Prim (loc, "IF_RIGHT", [right; left], annot) -> + ok @@ Some (Seq (loc, [Prim (loc, "IF_LEFT", [left; right], annot)])) + | Prim (_, "IF_RIGHT", args, _annot) -> + error (Invalid_arity ("IF_RIGHT", List.length args, 2)) + | _ -> + ok @@ None + +let expand_fail = function + | Prim (loc, "FAIL", [], []) -> + ok + @@ Some + (Seq + ( loc, + [Prim (loc, "UNIT", [], []); Prim (loc, "FAILWITH", [], [])] )) + | _ -> + ok @@ None + +let expand original = + let rec try_expansions = function + | [] -> + ok @@ original + | expander :: expanders -> ( + expander original + >>? function + | None -> try_expansions expanders | Some rewritten -> ok rewritten ) + in + try_expansions + [ expand_carn; + expand_cdrn; + expand_caddadr; + expand_set_caddadr; + expand_map_caddadr; + expand_deprecated_dxiiivp; + (* expand_paaiair ; *) + expand_pappaiir; + (* expand_unpaaiair ; *) + expand_unpappaiir; + expand_deprecated_duuuuup; + expand_compare; + expand_asserts; + expand_if_some; + expand_if_right; + expand_fail ] + +let expand_rec expr = + let rec error_map (expanded, errors) f = function + | [] -> + (List.rev expanded, List.rev errors) + | hd :: tl -> + let (new_expanded, new_errors) = f hd in + error_map + (new_expanded :: expanded, List.rev_append new_errors errors) + f + tl + in + let error_map = error_map ([], []) in + let rec expand_rec expr = + match expand expr with + | Ok expanded -> ( + match expanded with + | Seq (loc, items) -> + let (items, errors) = error_map expand_rec items in + (Seq (loc, items), errors) + | Prim (loc, name, args, annot) -> + let (args, errors) = error_map expand_rec args in + (Prim (loc, name, args, annot), errors) + | (Int _ | String _ | Bytes _) as atom -> + (atom, []) ) + | Error errors -> + (expr, errors) + in + expand_rec expr + +let unexpand_carn_and_cdrn expanded = + match expanded with + | Seq (loc, [Prim (_, "GET", [Int (locn, n)], annot)]) -> + let (half, parity) = Z.ediv_rem n (Z.of_int 2) in + if Z.(parity = zero) then + Some (Prim (loc, "CDR", [Int (locn, half)], annot)) + else Some (Prim (loc, "CAR", [Int (locn, half)], annot)) + | _ -> + None + +let unexpand_caddadr expanded = + let rec rsteps acc = function + | [] -> + Some acc + | Prim (_, "CAR", [], []) :: rest -> + rsteps ("A" :: acc) rest + | Prim (_, "CDR", [], []) :: rest -> + rsteps ("D" :: acc) rest + | _ -> + None + in + match expanded with + | Seq (loc, (Prim (_, "CAR", [], []) :: _ as nodes)) + | Seq (loc, (Prim (_, "CDR", [], []) :: _ as nodes)) -> ( + match rsteps [] nodes with + | Some steps -> + let name = String.concat "" ("C" :: List.rev ("R" :: steps)) in + Some (Prim (loc, name, [], [])) + | None -> + None ) + | _ -> + None + +let unexpand_set_caddadr expanded = + let rec steps acc annots = function + | Seq + ( loc, + [ Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], _); + Prim (_, "PAIR", [], _) ] ) -> + Some (loc, "A" :: acc, annots) + | Seq + ( loc, + [ Prim (_, "DUP", [], []); + Prim (_, "CAR", [], [field_annot]); + Prim (_, "DROP", [], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim (_, "PAIR", [], _) ] ) -> + Some (loc, "A" :: acc, field_annot :: annots) + | Seq (loc, [Prim (_, "CAR", [], _); Prim (_, "PAIR", [], _)]) -> + Some (loc, "D" :: acc, annots) + | Seq + ( loc, + [ Prim (_, "DUP", [], []); + Prim (_, "CDR", [], [field_annot]); + Prim (_, "DROP", [], []); + Prim (_, "CAR", [], _); + Prim (_, "PAIR", [], _) ] ) -> + Some (loc, "D" :: acc, field_annot :: annots) + | Seq + ( _, + [ Prim (_, "DUP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CAR", [], _); sub])], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim (_, "PAIR", [], pair_annots) ] ) -> + let (_, pair_annots) = extract_field_annots pair_annots in + steps ("A" :: acc) (List.rev_append pair_annots annots) sub + | Seq + ( _, + [ Prim (_, "DUP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], _); sub])], []); + Prim (_, "CAR", [], _); + Prim (_, "PAIR", [], pair_annots) ] ) -> + let (_, pair_annots) = extract_field_annots pair_annots in + steps ("D" :: acc) (List.rev_append pair_annots annots) sub + | _ -> + None + in + match steps [] [] expanded with + | Some (loc, steps, annots) -> + let name = String.concat "" ("SET_C" :: List.rev ("R" :: steps)) in + Some (Prim (loc, name, [], List.rev annots)) + | None -> + None + +let unexpand_map_caddadr expanded = + let rec steps acc annots = function + | Seq + ( loc, + [ Prim (_, "DUP", [], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CAR", [], []); code])], []); + Prim (_, "PAIR", [], _) ] ) -> + Some (loc, "A" :: acc, annots, code) + | Seq + ( loc, + [ Prim (_, "DUP", [], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim + ( _, + "DIP", + [Seq (_, [Prim (_, "CAR", [], [field_annot]); code])], + [] ); + Prim (_, "PAIR", [], _) ] ) -> + Some (loc, "A" :: acc, field_annot :: annots, code) + | Seq + ( loc, + [ Prim (_, "DUP", [], []); + Prim (_, "CDR", [], []); + code; + Prim (_, "SWAP", [], []); + Prim (_, "CAR", [], _); + Prim (_, "PAIR", [], _) ] ) -> + Some (loc, "D" :: acc, annots, code) + | Seq + ( loc, + [ Prim (_, "DUP", [], []); + Prim (_, "CDR", [], [field_annot]); + code; + Prim (_, "SWAP", [], []); + Prim (_, "CAR", [], _); + Prim (_, "PAIR", [], _) ] ) -> + Some (loc, "D" :: acc, field_annot :: annots, code) + | Seq + ( _, + [ Prim (_, "DUP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CAR", [], _); sub])], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim (_, "PAIR", [], pair_annots) ] ) -> + let (_, pair_annots) = extract_field_annots pair_annots in + steps ("A" :: acc) (List.rev_append pair_annots annots) sub + | Seq + ( _, + [ Prim (_, "DUP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], []); sub])], []); + Prim (_, "CAR", [], []); + Prim (_, "PAIR", [], pair_annots) ] ) -> + let (_, pair_annots) = extract_field_annots pair_annots in + steps ("D" :: acc) (List.rev_append pair_annots annots) sub + | _ -> + None + in + match steps [] [] expanded with + | Some (loc, steps, annots, code) -> + let name = String.concat "" ("MAP_C" :: List.rev ("R" :: steps)) in + Some (Prim (loc, name, [code], List.rev annots)) + | None -> + None + +let unexpand_deprecated_dxiiivp expanded = + (* transparently turn the old expansion of deprecated [DI...IP] to [DIP n] *) + match expanded with + | Seq + ( loc, + [Prim (_, "DIP", [(Seq (_, [Prim (_, "DIP", [_], [])]) as sub)], [])] + ) -> + let rec count acc = function + | Seq (_, [Prim (_, "DIP", [sub], [])]) -> + count (acc + 1) sub + | sub -> + (acc, sub) + in + let (depth, sub) = count 1 sub in + Some (Prim (loc, "DIP", [Int (loc, Z.of_int depth); sub], [])) + | _ -> + None + +let unexpand_dupn expanded = + match expanded with + | Seq + ( loc, + [ Prim + (_, "DIP", [Int (_, np); Seq (_, [Prim (_, "DUP", [], annot)])], []); + Prim (_, "DIG", [Int (nloc, ng)], []) ] ) + when Z.equal np (Z.pred ng) -> + Some (Prim (loc, "DUP", [Int (nloc, ng)], annot)) + | _ -> + None + +let unexpand_deprecated_duuuuup expanded = + (* transparently turn the old expansion of deprecated [DU...UP] to [DUP n] *) + let rec expand n = function + | Seq (loc, [Prim (nloc, "DUP", [], annot)]) -> + if n = 1 then None + else Some (Prim (loc, "DUP", [Int (nloc, Z.of_int n)], annot)) + | Seq (_, [Prim (_, "DIP", [expanded'], []); Prim (_, "SWAP", [], [])]) -> + expand (n + 1) expanded' + | _ -> + None + in + expand 1 expanded + +let rec normalize_pair_item ?(right = false) = function + | P (i, a, b) -> + P (i, normalize_pair_item a, normalize_pair_item ~right:true b) + | A when right -> + I + | A -> + A + | I -> + I + +let unexpand_pappaiir expanded = + match expanded with + | Seq (_, [Prim (_, "PAIR", [], [])]) -> + Some expanded + | Seq (loc, (_ :: _ as nodes)) -> ( + let rec exec stack nodes = + match (nodes, stack) with + | ([], _) -> + stack + (* support new expansion using [DIP n] *) + | ( Prim (ploc, "DIP", [Int (loc, n); Seq (sloc, sub)], []) :: rest, + a :: rstack ) + when Z.to_int n > 1 -> + exec + ( a + :: exec + rstack + [ Prim + (ploc, "DIP", [Int (loc, Z.pred n); Seq (sloc, sub)], []) + ] ) + rest + | (Prim (_, "DIP", [Int (_, n); Seq (_, sub)], []) :: rest, a :: rstack) + when Z.to_int n = 1 -> + exec (a :: exec rstack sub) rest + | (Prim (ploc, "DIP", [Int (loc, n); Seq (sloc, sub)], []) :: rest, []) + when Z.to_int n > 1 -> + exec + ( A + :: exec + [] + [ Prim + (ploc, "DIP", [Int (loc, Z.pred n); Seq (sloc, sub)], []) + ] ) + rest + | (Prim (_, "DIP", [Int (_, n); Seq (_, sub)], []) :: rest, []) + when Z.to_int n = 1 -> + exec (A :: exec [] sub) rest + (* support old expansion using [DIP] *) + | (Prim (_, "DIP", [Seq (_, sub)], []) :: rest, a :: rstack) -> + exec (a :: exec rstack sub) rest + | (Prim (_, "DIP", [Seq (_, sub)], []) :: rest, []) -> + exec (A :: exec [] sub) rest + | (Prim (_, "PAIR", [], []) :: rest, a :: b :: rstack) -> + exec (P (0, a, b) :: rstack) rest + | (Prim (_, "PAIR", [], []) :: rest, [a]) -> + exec [P (0, a, I)] rest + | (Prim (_, "PAIR", [], []) :: rest, []) -> + exec [P (0, A, I)] rest + | _ -> + raise_notrace Not_a_pair + in + match exec [] nodes with + | [] -> + None + | res :: _ -> + let res = normalize_pair_item res in + let name = unparse_pair_item res in + Some (Prim (loc, name, [], [])) + | exception Not_a_pair -> + None ) + | _ -> + None + +let unexpand_unpappaiir expanded = + match expanded with + | Seq (loc, (_ :: _ as nodes)) -> ( + let rec exec stack nodes = + match (nodes, stack) with + | ([], _) -> + stack + (* support new expansion using [DIP n] *) + | ( Prim (ploc, "DIP", [Int (loc, n); Seq (sloc, sub)], []) :: rest, + a :: rstack ) + when Z.to_int n > 1 -> + exec + ( a + :: exec + rstack + [ Prim + (ploc, "DIP", [Int (loc, Z.pred n); Seq (sloc, sub)], []) + ] ) + rest + | (Prim (_, "DIP", [Int (_, n); Seq (_, sub)], []) :: rest, a :: rstack) + when Z.to_int n = 1 -> + exec (a :: exec rstack sub) rest + | (Prim (ploc, "DIP", [Int (loc, n); Seq (sloc, sub)], []) :: rest, []) + when Z.to_int n > 1 -> + exec + ( A + :: exec + [] + [ Prim + (ploc, "DIP", [Int (loc, Z.pred n); Seq (sloc, sub)], []) + ] ) + rest + | (Prim (_, "DIP", [Int (_, n); Seq (_, sub)], []) :: rest, []) + when Z.to_int n = 1 -> + exec (A :: exec [] sub) rest + (* support old expansion using [DIP] *) + | (Prim (_, "DIP", [Seq (_, sub)], []) :: rest, a :: rstack) -> + exec (a :: exec rstack sub) rest + | (Prim (_, "DIP", [Seq (_, sub)], []) :: rest, []) -> + exec (A :: exec [] sub) rest + | ( Seq + ( _, + [ Prim (_, "DUP", [], []); + Prim (_, "CAR", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], [])])], []) ] + ) + :: rest, + a :: b :: rstack ) -> + exec (P (0, a, b) :: rstack) rest + | ( Seq + ( _, + [ Prim (_, "DUP", [], []); + Prim (_, "CAR", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], [])])], []) ] + ) + :: rest, + [a] ) -> + exec [P (0, a, I)] rest + | ( Seq + ( _, + [ Prim (_, "DUP", [], []); + Prim (_, "CAR", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], [])])], []) ] + ) + :: rest, + [] ) -> + exec [P (0, A, I)] rest + | _ -> + raise_notrace Not_a_pair + in + match exec [] (List.rev nodes) with + | [] -> + None + | res :: _ -> + let res = normalize_pair_item res in + let name = "UN" ^ unparse_pair_item res in + Some (Prim (loc, name, [], [])) + | exception Not_a_pair -> + None ) + | _ -> + None + +let unexpand_compare expanded = + match expanded with + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "EQ", [], annot)]) -> + Some (Prim (loc, "CMPEQ", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "NEQ", [], annot)]) -> + Some (Prim (loc, "CMPNEQ", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "LT", [], annot)]) -> + Some (Prim (loc, "CMPLT", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "GT", [], annot)]) -> + Some (Prim (loc, "CMPGT", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "LE", [], annot)]) -> + Some (Prim (loc, "CMPLE", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "GE", [], annot)]) -> + Some (Prim (loc, "CMPGE", [], annot)) + | Seq + ( loc, + [ Prim (_, "COMPARE", [], _); + Prim (_, "EQ", [], _); + Prim (_, "IF", args, annot) ] ) -> + Some (Prim (loc, "IFCMPEQ", args, annot)) + | Seq + ( loc, + [ Prim (_, "COMPARE", [], _); + Prim (_, "NEQ", [], _); + Prim (_, "IF", args, annot) ] ) -> + Some (Prim (loc, "IFCMPNEQ", args, annot)) + | Seq + ( loc, + [ Prim (_, "COMPARE", [], _); + Prim (_, "LT", [], _); + Prim (_, "IF", args, annot) ] ) -> + Some (Prim (loc, "IFCMPLT", args, annot)) + | Seq + ( loc, + [ Prim (_, "COMPARE", [], _); + Prim (_, "GT", [], _); + Prim (_, "IF", args, annot) ] ) -> + Some (Prim (loc, "IFCMPGT", args, annot)) + | Seq + ( loc, + [ Prim (_, "COMPARE", [], _); + Prim (_, "LE", [], _); + Prim (_, "IF", args, annot) ] ) -> + Some (Prim (loc, "IFCMPLE", args, annot)) + | Seq + ( loc, + [ Prim (_, "COMPARE", [], _); + Prim (_, "GE", [], _); + Prim (_, "IF", args, annot) ] ) -> + Some (Prim (loc, "IFCMPGE", args, annot)) + | Seq (loc, [Prim (_, "EQ", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFEQ", args, annot)) + | Seq (loc, [Prim (_, "NEQ", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFNEQ", args, annot)) + | Seq (loc, [Prim (_, "LT", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFLT", args, annot)) + | Seq (loc, [Prim (_, "GT", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFGT", args, annot)) + | Seq (loc, [Prim (_, "LE", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFLE", args, annot)) + | Seq (loc, [Prim (_, "GE", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFGE", args, annot)) + | _ -> + None + +let unexpand_asserts expanded = + match expanded with + | Seq + ( loc, + [ Prim + ( _, + "IF", + [ Seq (_, []); + Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT", [], [])) + | Seq + ( loc, + [ Seq (_, [Prim (_, "COMPARE", [], []); Prim (_, comparison, [], [])]); + Prim + ( _, + "IF", + [ Seq (_, []); + Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_CMP" ^ comparison, [], [])) + | Seq + ( loc, + [ Prim (_, comparison, [], []); + Prim + ( _, + "IF", + [ Seq (_, []); + Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_" ^ comparison, [], [])) + | Seq + ( loc, + [ Prim + ( _, + "IF_NONE", + [ Seq (_, [Prim (_, "RENAME", [], annot)]); + Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_NONE", [], annot)) + | Seq + ( loc, + [ Prim + ( _, + "IF_NONE", + [ Seq (_, []); + Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_NONE", [], [])) + | Seq + ( loc, + [ Prim + ( _, + "IF_NONE", + [ Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ); + Seq (_, []) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_SOME", [], [])) + | Seq + ( loc, + [ Prim + ( _, + "IF_NONE", + [ Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ); + Seq (_, [Prim (_, "RENAME", [], annot)]) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_SOME", [], annot)) + | Seq + ( loc, + [ Prim + ( _, + "IF_LEFT", + [ Seq (_, []); + Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_LEFT", [], [])) + | Seq + ( loc, + [ Prim + ( _, + "IF_LEFT", + [ Seq (_, [Prim (_, "RENAME", [], annot)]); + Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_LEFT", [], annot)) + | Seq + ( loc, + [ Prim + ( _, + "IF_LEFT", + [ Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ); + Seq (_, []) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_RIGHT", [], [])) + | Seq + ( loc, + [ Prim + ( _, + "IF_LEFT", + [ Seq + ( _, + [ Seq + ( _, + [ Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []) ] ) ] ); + Seq (_, [Prim (_, "RENAME", [], annot)]) ], + [] ) ] ) -> + Some (Prim (loc, "ASSERT_RIGHT", [], annot)) + | _ -> + None + +let unexpand_if_some = function + | Seq (loc, [Prim (_, "IF_NONE", [left; right], annot)]) -> + Some (Prim (loc, "IF_SOME", [right; left], annot)) + | _ -> + None + +let unexpand_if_right = function + | Seq (loc, [Prim (_, "IF_LEFT", [left; right], annot)]) -> + Some (Prim (loc, "IF_RIGHT", [right; left], annot)) + | _ -> + None + +let unexpand_fail = function + | Seq (loc, [Prim (_, "UNIT", [], []); Prim (_, "FAILWITH", [], [])]) -> + Some (Prim (loc, "FAIL", [], [])) + | _ -> + None + +let unexpand original = + let try_unexpansions unexpanders = + match + List.fold_left + (fun acc f -> + match acc with + | None -> + f original + | Some rewritten -> + Some rewritten) + None + unexpanders + with + | None -> + original + | Some rewritten -> + rewritten + in + try_unexpansions + [ unexpand_asserts; + unexpand_carn_and_cdrn; + unexpand_caddadr; + unexpand_set_caddadr; + unexpand_map_caddadr; + unexpand_deprecated_dxiiivp; + unexpand_pappaiir; + unexpand_unpappaiir; + unexpand_deprecated_duuuuup; + unexpand_dupn; + unexpand_compare; + unexpand_if_some; + unexpand_if_right; + unexpand_fail ] + +(* + If an argument of Prim is a sequence, we do not want to unexpand + its root in case the source already contains an expanded macro. In + which case unexpansion would remove surrounding braces and generate + ill-formed code. + + For example, DIIP { DIP { DUP }; SWAP } is not unexpandable but + DIIP {{ DIP { DUP }; SWAP }} (note the double braces) is unexpanded + to DIIP { DUUP }. + + unexpand_rec_but_root is the same as unexpand_rec but does not try + to unexpand at root *) + +let rec unexpand_rec expr = unexpand_rec_but_root (unexpand expr) + +and unexpand_rec_but_root = function + | Seq (loc, items) -> + Seq (loc, List.map unexpand_rec items) + | Prim (loc, name, args, annot) -> + Prim (loc, name, List.map unexpand_rec_but_root args, annot) + | (Int _ | String _ | Bytes _) as atom -> + atom + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"michelson.macros.unexpected_annotation" + ~title:"Unexpected annotation" + ~description: + "A macro had an annotation, but no annotation was permitted on this \ + macro." + ~pp:(fun ppf -> Format.fprintf ppf "Unexpected annotation on macro %s.") + (obj1 (req "macro_name" string)) + (function Unexpected_macro_annotation str -> Some str | _ -> None) + (fun s -> Unexpected_macro_annotation s) ; + register_error_kind + `Permanent + ~id:"michelson.macros.sequence_expected" + ~title:"Macro expects a sequence" + ~description:"An macro expects a sequence, but a sequence was not provided" + ~pp:(fun ppf name -> + Format.fprintf + ppf + "Macro %s expects a sequence, but did not receive one." + name) + (obj1 (req "macro_name" string)) + (function Sequence_expected name -> Some name | _ -> None) + (fun name -> Sequence_expected name) ; + register_error_kind + `Permanent + ~id:"michelson.macros.bas_arity" + ~title:"Wrong number of arguments to macro" + ~description:"A wrong number of arguments was provided to a macro" + ~pp:(fun ppf (name, got, exp) -> + Format.fprintf + ppf + "Macro %s expects %d arguments, was given %d." + name + exp + got) + (obj3 + (req "macro_name" string) + (req "given_number_of_arguments" uint16) + (req "expected_number_of_arguments" uint16)) + (function + | Invalid_arity (name, got, exp) -> Some (name, got, exp) | _ -> None) + (fun (name, got, exp) -> Invalid_arity (name, got, exp)) diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_macros.mli b/src/proto_009_PsFLoren/lib_client/michelson_v1_macros.mli new file mode 100644 index 0000000000000000000000000000000000000000..352a59b00a9e9f00c927b90690d1189874510d90 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_macros.mli @@ -0,0 +1,86 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Tezos_micheline + +type 'l node = ('l, string) Micheline.node + +type error += Unexpected_macro_annotation of string + +type error += Sequence_expected of string + +type error += Invalid_arity of string * int * int + +val expand : 'l node -> 'l node tzresult + +val expand_rec : 'l node -> 'l node * error list + +val expand_caddadr : 'l node -> 'l node option tzresult + +val expand_set_caddadr : 'l node -> 'l node option tzresult + +val expand_map_caddadr : 'l node -> 'l node option tzresult + +val expand_deprecated_dxiiivp : 'l node -> 'l node option tzresult + +val expand_pappaiir : 'l node -> 'l node option tzresult + +val expand_deprecated_duuuuup : 'l node -> 'l node option tzresult + +val expand_compare : 'l node -> 'l node option tzresult + +val expand_asserts : 'l node -> 'l node option tzresult + +val expand_unpappaiir : 'l node -> 'l node option tzresult + +val expand_if_some : 'l node -> 'l node option tzresult + +val expand_if_right : 'l node -> 'l node option tzresult + +val unexpand : 'l node -> 'l node + +val unexpand_rec : 'l node -> 'l node + +val unexpand_caddadr : 'l node -> 'l node option + +val unexpand_set_caddadr : 'l node -> 'l node option + +val unexpand_map_caddadr : 'l node -> 'l node option + +val unexpand_deprecated_dxiiivp : 'l node -> 'l node option + +val unexpand_pappaiir : 'l node -> 'l node option + +val unexpand_deprecated_duuuuup : 'l node -> 'l node option + +val unexpand_compare : 'l node -> 'l node option + +val unexpand_asserts : 'l node -> 'l node option + +val unexpand_unpappaiir : 'l node -> 'l node option + +val unexpand_if_some : 'l node -> 'l node option + +val unexpand_if_right : 'l node -> 'l node option diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_parser.ml b/src/proto_009_PsFLoren/lib_client/michelson_v1_parser.ml new file mode 100644 index 0000000000000000000000000000000000000000..8d7dafcb083c1eb70ee1428991d2d755b79bd691 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_parser.ml @@ -0,0 +1,107 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Tezos_micheline +open Micheline_parser +open Micheline + +type parsed = { + source : string; + unexpanded : string canonical; + expanded : Michelson_v1_primitives.prim canonical; + expansion_table : (int * (Micheline_parser.location * int list)) list; + unexpansion_table : (int * int) list; +} + +(* Unexpanded toplevel expression should be a sequence *) +let expand_all source ast errors = + let (unexpanded, loc_table) = extract_locations ast in + let (expanded, expansion_errors) = + Michelson_v1_macros.expand_rec (root unexpanded) + in + let (expanded, unexpansion_table) = extract_locations expanded in + let expansion_table = + let sorted = + List.sort (fun (_, a) (_, b) -> compare a b) unexpansion_table + in + let grouped = + let rec group = function + | (acc, []) -> + acc + | ([], (u, e) :: r) -> + group ([(e, [u])], r) + | (((pe, us) :: racc as acc), (u, e) :: r) -> + if e = pe then group ((e, u :: us) :: racc, r) + else group ((e, [u]) :: acc, r) + in + group ([], sorted) + in + match + List.map2 + ~when_different_lengths:() + (fun (l, ploc) (l', elocs) -> + assert (l = l') ; + (l, (ploc, elocs))) + (List.sort compare loc_table) + (List.sort compare grouped) + with + | Ok v -> + v + | Error () -> + invalid_arg "Michelson_v1_parser.expand_all" + in + match Michelson_v1_primitives.prims_of_strings expanded with + | Ok expanded -> + ( {source; unexpanded; expanded; expansion_table; unexpansion_table}, + errors @ expansion_errors ) + | Error errs -> + let errs = Environment.wrap_tztrace errs in + ( { + source; + unexpanded; + expanded = Micheline.strip_locations (Seq ((), [])); + expansion_table; + unexpansion_table; + }, + errors @ expansion_errors @ errs ) + +let parse_toplevel ?check source = + let (tokens, lexing_errors) = Micheline_parser.tokenize source in + let (asts, parsing_errors) = Micheline_parser.parse_toplevel ?check tokens in + let ast = + let start = min_point asts and stop = max_point asts in + Seq ({start; stop}, asts) + in + expand_all source ast (lexing_errors @ parsing_errors) + +let parse_expression ?check source = + let (tokens, lexing_errors) = Micheline_parser.tokenize source in + let (ast, parsing_errors) = + Micheline_parser.parse_expression ?check tokens + in + expand_all source ast (lexing_errors @ parsing_errors) + +let expand_all ~source ~original = expand_all source original [] diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_parser.mli b/src/proto_009_PsFLoren/lib_client/michelson_v1_parser.mli new file mode 100644 index 0000000000000000000000000000000000000000..4f55e20943faf4cfa5f8f8abe62ba4aee1e33b71 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_parser.mli @@ -0,0 +1,53 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline + +(** The result of parsing and expanding a Michelson V1 script or data. *) +type parsed = { + source : string; (** The original source code. *) + unexpanded : string Micheline.canonical; + (** Original expression with macros. *) + expanded : Script.expr; (** Expression with macros fully expanded. *) + expansion_table : (int * (Micheline_parser.location * int list)) list; + (** Associates unexpanded nodes to their parsing locations and + the nodes expanded from it in the expanded expression. *) + unexpansion_table : (int * int) list; + (** Associates an expanded node to its source in the unexpanded + expression. *) +} + +val parse_toplevel : + ?check:bool -> string -> parsed Micheline_parser.parsing_result + +val parse_expression : + ?check:bool -> string -> parsed Micheline_parser.parsing_result + +val expand_all : + source:string -> + original:Micheline_parser.node -> + parsed Micheline_parser.parsing_result diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_printer.ml b/src/proto_009_PsFLoren/lib_client/michelson_v1_printer.ml new file mode 100644 index 0000000000000000000000000000000000000000..4065060a5d9f4957c6d27afa6389a5f43831c13c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_printer.ml @@ -0,0 +1,258 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline +open Micheline +open Micheline_printer + +let anon = {comment = None} + +let print_expr ppf expr = + expr |> Michelson_v1_primitives.strings_of_prims + |> Micheline.inject_locations (fun _ -> anon) + |> print_expr ppf + +let print_expr_unwrapped ppf expr = + expr |> Michelson_v1_primitives.strings_of_prims + |> Micheline.inject_locations (fun _ -> anon) + |> print_expr_unwrapped ppf + +let print_var_annots ppf = List.iter (Format.fprintf ppf "%s ") + +let print_annot_expr_unwrapped ppf (expr, annot) = + Format.fprintf ppf "%a%a" print_var_annots annot print_expr_unwrapped expr + +let print_stack ppf = function + | [] -> + Format.fprintf ppf "[]" + | more -> + Format.fprintf + ppf + "@[[ %a ]@]" + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf "@ : ") + print_annot_expr_unwrapped) + more + +let print_execution_trace ppf trace = + Format.pp_print_list + (fun ppf (loc, gas, stack) -> + Format.fprintf + ppf + "- @[location: %d (remaining gas: %a)@,[ @[%a ]@]@]" + loc + Gas.pp + gas + (Format.pp_print_list (fun ppf (e, annot) -> + Format.fprintf + ppf + "@[%a \t%s@]" + print_expr + e + (match annot with None -> "" | Some a -> a))) + stack) + ppf + trace + +let print_big_map_diff ppf lazy_storage_diff = + let diff = + Contract.Legacy_big_map_diff.of_lazy_storage_diff lazy_storage_diff + in + let pp_map ppf id = + if Compare.Z.(id < Z.zero) then + Format.fprintf ppf "temp(%s)" (Z.to_string (Z.neg id)) + else Format.fprintf ppf "map(%s)" (Z.to_string id) + in + Format.fprintf + ppf + "@[%a@]" + (Format.pp_print_list ~pp_sep:Format.pp_print_space (fun ppf -> + function + | Contract.Legacy_big_map_diff.Clear id -> + Format.fprintf ppf "Clear %a" pp_map id + | Contract.Legacy_big_map_diff.Alloc {big_map; key_type; value_type} -> + Format.fprintf + ppf + "New %a of type (big_map %a %a)" + pp_map + big_map + print_expr + key_type + print_expr + value_type + | Contract.Legacy_big_map_diff.Copy {src; dst} -> + Format.fprintf ppf "Copy %a to %a" pp_map src pp_map dst + | Contract.Legacy_big_map_diff.Update {big_map; diff_key; diff_value; _} + -> + Format.fprintf + ppf + "%s %a[%a]%a" + (match diff_value with None -> "Unset" | Some _ -> "Set") + pp_map + big_map + print_expr + diff_key + (fun ppf -> function None -> () | Some x -> + Format.fprintf ppf " to %a" print_expr x) + diff_value)) + (diff :> Contract.Legacy_big_map_diff.item list) + +let inject_types type_map parsed = + let rec inject_expr = function + | Seq (loc, items) -> + Seq (inject_loc `before loc, List.map inject_expr items) + | Prim (loc, name, items, annot) -> + Prim (inject_loc `after loc, name, List.map inject_expr items, annot) + | Int (loc, value) -> + Int (inject_loc `after loc, value) + | String (loc, value) -> + String (inject_loc `after loc, value) + | Bytes (loc, value) -> + Bytes (inject_loc `after loc, value) + and inject_loc which loc = + let comment = + let ( >?? ) = Option.bind in + List.assoc loc parsed.Michelson_v1_parser.expansion_table + >?? fun (_, locs) -> + let locs = List.sort compare locs in + List.hd locs + >?? fun head_loc -> + List.assoc head_loc type_map + >?? fun (bef, aft) -> + let stack = match which with `before -> bef | `after -> aft in + Some (Format.asprintf "%a" print_stack stack) + in + {comment} + in + inject_expr (root parsed.unexpanded) + +let unparse ?type_map parse expanded = + let source = + match type_map with + | Some type_map -> + let (unexpanded, unexpansion_table) = + expanded |> Michelson_v1_primitives.strings_of_prims |> root + |> Michelson_v1_macros.unexpand_rec |> Micheline.extract_locations + in + let rec inject_expr = function + | Seq (loc, items) -> + Seq (inject_loc `before loc, List.map inject_expr items) + | Prim (loc, name, items, annot) -> + Prim + (inject_loc `after loc, name, List.map inject_expr items, annot) + | Int (loc, value) -> + Int (inject_loc `after loc, value) + | String (loc, value) -> + String (inject_loc `after loc, value) + | Bytes (loc, value) -> + Bytes (inject_loc `after loc, value) + and inject_loc which loc = + let comment = + let ( >?? ) = Option.bind in + List.assoc loc unexpansion_table + >?? fun loc -> + List.assoc loc type_map + >?? fun (bef, aft) -> + let stack = match which with `before -> bef | `after -> aft in + Some (Format.asprintf "%a" print_stack stack) + in + {comment} + in + unexpanded |> root |> inject_expr + |> Format.asprintf "%a" Micheline_printer.print_expr + | None -> + expanded |> Michelson_v1_primitives.strings_of_prims |> root + |> Michelson_v1_macros.unexpand_rec |> Micheline.strip_locations + |> Micheline_printer.printable (fun n -> n) + |> Format.asprintf "%a" Micheline_printer.print_expr + in + match parse source with + | (res, []) -> + res + | (_, _ :: _) -> + Stdlib.failwith "Michelson_v1_printer.unparse" + +let unparse_toplevel ?type_map = + unparse ?type_map Michelson_v1_parser.parse_toplevel + +let unparse_expression = unparse Michelson_v1_parser.parse_expression + +let unparse_invalid expanded = + let source = + expanded |> root |> Michelson_v1_macros.unexpand_rec + |> Micheline.strip_locations + |> Micheline_printer.printable (fun n -> n) + |> Format.asprintf "%a" Micheline_printer.print_expr_unwrapped + in + fst (Michelson_v1_parser.parse_toplevel source) + +let ocaml_constructor_of_prim prim = + (* Assuming all the prim constructor prefixes match the + [[Michelson_v1_primitives.namespace]]. *) + let prefix = + Michelson_v1_primitives.(namespace prim |> string_of_namespace) + in + Format.asprintf "%s_%s" prefix @@ Michelson_v1_primitives.string_of_prim prim + +let micheline_string_of_expression ~zero_loc expression = + let string_of_list : string list -> string = + fun xs -> String.concat "; " xs |> Format.asprintf "[%s]" + in + let show_loc loc = if zero_loc then 0 else loc in + let rec string_of_node = function + | Int (loc, i) -> + let z = + match Z.to_int i with + | 0 -> + "Z.zero" + | 1 -> + "Z.one" + | i -> + Format.asprintf "Z.of_int %d" i + in + Format.asprintf "Int (%d, %s)" (show_loc loc) z + | String (loc, s) -> + Format.asprintf "String (%d, \"%s\")" (show_loc loc) s + | Bytes (loc, b) -> + Format.asprintf + "Bytes (%d, Bytes.of_string \"%s\")" + (show_loc loc) + Bytes.(escaped b |> to_string) + | Prim (loc, prim, nodes, annot) -> + Format.asprintf + "Prim (%d, %s, %s, %s)" + (show_loc loc) + (ocaml_constructor_of_prim prim) + (string_of_list @@ List.map string_of_node nodes) + (string_of_list @@ List.map (Format.asprintf "\"%s\"") annot) + | Seq (loc, nodes) -> + Format.asprintf + "Seq (%d, %s)" + (show_loc loc) + (string_of_list @@ List.map string_of_node nodes) + in + string_of_node (root expression) diff --git a/src/proto_009_PsFLoren/lib_client/michelson_v1_printer.mli b/src/proto_009_PsFLoren/lib_client/michelson_v1_printer.mli new file mode 100644 index 0000000000000000000000000000000000000000..07cb29ae8556c7a83037cd7c4907f2a1e41e092c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/michelson_v1_printer.mli @@ -0,0 +1,65 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline + +val print_expr : Format.formatter -> Script_repr.expr -> unit + +val print_expr_unwrapped : Format.formatter -> Script_repr.expr -> unit + +val print_execution_trace : + Format.formatter -> + (Script.location * Gas.t * (Script.expr * string option) list) list -> + unit + +val print_big_map_diff : Format.formatter -> Lazy_storage.diffs -> unit + +(** Insert the type map returned by the typechecker as comments in a + printable Micheline AST. *) +val inject_types : + Script_tc_errors.type_map -> + Michelson_v1_parser.parsed -> + Micheline_printer.node + +(** Unexpand the macros and produce the result of parsing an + intermediate pretty printed source. Useful when working with + contracts extracted from the blockchain and not local files. *) +val unparse_toplevel : + ?type_map:Script_tc_errors.type_map -> + Script.expr -> + Michelson_v1_parser.parsed + +val unparse_expression : Script.expr -> Michelson_v1_parser.parsed + +(** Unexpand the macros and produce the result of parsing an + intermediate pretty printed source. Works on generic trees,for + programs that fail to be converted to a specific script version. *) +val unparse_invalid : string Micheline.canonical -> Michelson_v1_parser.parsed + +val ocaml_constructor_of_prim : Michelson_v1_primitives.prim -> string + +val micheline_string_of_expression : zero_loc:bool -> Script.expr -> string diff --git a/src/proto_009_PsFLoren/lib_client/mockup.ml b/src/proto_009_PsFLoren/lib_client/mockup.ml new file mode 100644 index 0000000000000000000000000000000000000000..709bb78811a438b65c12fada2f142e86348eea04 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/mockup.ml @@ -0,0 +1,513 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +(* ------------------------------------------------------------------------- *) +(* Mockup protocol parameters *) + +type mockup_protocol_parameters = { + initial_timestamp : Time.Protocol.t; + bootstrap_accounts : Parameters.bootstrap_account list; + bootstrap_contracts : Parameters.bootstrap_contract list; + constants : Constants.parametric; +} + +type protocol_constants_overrides = { + hard_gas_limit_per_operation : Gas.Arith.integral option; + hard_gas_limit_per_block : Gas.Arith.integral option; + hard_storage_limit_per_operation : Z.t option; + cost_per_byte : Tez.t option; + chain_id : Chain_id.t option; + timestamp : Time.Protocol.t option; +} + +type parsed_account_repr = { + name : string; + sk_uri : Client_keys.sk_uri; + amount : Tez.t; +} + +let parsed_account_repr_pp ppf account = + let open Format in + let format_amount ppf value = fprintf ppf "amount:%a" Tez.pp value in + fprintf + ppf + "@[name:%s@,sk_uri:%s@,%a@]" + account.name + (Uri.to_string (account.sk_uri :> Uri.t)) + format_amount + account.amount + +let bootstrap_account_encoding : Parameters.bootstrap_account Data_encoding.t = + let open Data_encoding in + let open Parameters in + conv + (fun {public_key_hash; public_key; amount} -> + (public_key_hash, public_key, amount)) + (fun (public_key_hash, public_key, amount) -> + {public_key_hash; public_key; amount}) + (obj3 + (req "public_key_hash" Signature.Public_key_hash.encoding) + (opt "public_key" Signature.Public_key.encoding) + (req "amount" Tez.encoding)) + +let bootstrap_contract_encoding : Parameters.bootstrap_contract Data_encoding.t + = + let open Data_encoding in + let open Parameters in + conv + (fun {delegate; amount; script} -> (delegate, amount, script)) + (fun (delegate, amount, script) -> {delegate; amount; script}) + (obj3 + (req "delegate" Signature.Public_key_hash.encoding) + (req "amount" Tez.encoding) + (req "script" Script.encoding)) + +let mockup_protocol_parameters_encoding : + mockup_protocol_parameters Data_encoding.t = + let open Data_encoding in + conv + (fun p -> + ( p.initial_timestamp, + p.bootstrap_accounts, + p.bootstrap_contracts, + p.constants )) + (fun (initial_timestamp, bootstrap_accounts, bootstrap_contracts, constants) + -> + {initial_timestamp; bootstrap_accounts; bootstrap_contracts; constants}) + (obj4 + (req "initial_timestamp" Time.Protocol.encoding) + (req "bootstrap_accounts" (list bootstrap_account_encoding)) + (req "bootstrap_contracts" (list bootstrap_contract_encoding)) + (req "constants" Constants.parametric_encoding)) + +let protocol_constants_overrides_encoding = + let open Data_encoding in + conv + (fun p -> + ( p.hard_gas_limit_per_operation, + p.hard_gas_limit_per_block, + p.hard_storage_limit_per_operation, + p.cost_per_byte, + p.chain_id, + p.timestamp )) + (fun ( hard_gas_limit_per_operation, + hard_gas_limit_per_block, + hard_storage_limit_per_operation, + cost_per_byte, + chain_id, + timestamp ) -> + { + hard_gas_limit_per_operation; + hard_gas_limit_per_block; + hard_storage_limit_per_operation; + cost_per_byte; + chain_id; + timestamp; + }) + (obj6 + (opt "hard_gas_limit_per_operation" Gas.Arith.z_integral_encoding) + (opt "hard_gas_limit_per_block" Gas.Arith.z_integral_encoding) + (opt "hard_storage_limit_per_operation" z) + (opt "cost_per_byte" Tez.encoding) + (opt "chain_id" Chain_id.encoding) + (opt "initial_timestamp" Time.Protocol.encoding)) + +let default_mockup_parameters : mockup_protocol_parameters = + let parameters = + Default_parameters.parameters_of_constants + Default_parameters.constants_sandbox + in + { + initial_timestamp = Time.Protocol.epoch; + bootstrap_accounts = parameters.bootstrap_accounts; + bootstrap_contracts = parameters.bootstrap_contracts; + constants = parameters.constants; + } + +let default_mockup_protocol_constants + (cctxt : Tezos_client_base.Client_context.full) : + protocol_constants_overrides tzresult Lwt.t = + let cpctxt = new Protocol_client_context.wrap_full cctxt in + Protocol.Constants_services.all cpctxt (cpctxt#chain, cpctxt#block) + >>=? fun constants_t -> + let { Protocol.Alpha_context.Constants.hard_gas_limit_per_operation; + hard_gas_limit_per_block; + hard_storage_limit_per_operation; + cost_per_byte; + _ } = + constants_t.parametric + in + let to_chain_id_opt = function `Hash c -> Some c | _ -> None in + Shell_services.Blocks.Header.shell_header + cpctxt + ~chain:cpctxt#chain + ~block:cpctxt#block + () + >>=? fun header -> + return + { + hard_gas_limit_per_operation = Some hard_gas_limit_per_operation; + hard_gas_limit_per_block = Some hard_gas_limit_per_block; + hard_storage_limit_per_operation = Some hard_storage_limit_per_operation; + cost_per_byte = Some cost_per_byte; + chain_id = to_chain_id_opt cpctxt#chain; + timestamp = Some header.timestamp; + } + +(* Use the wallet to convert a bootstrap account's public key + into a parsed_account_repr secret key Uri *) +let bootstrap_account_to_parsed_account_repr cctxt + (bootstrap_account : Parameters.bootstrap_account) = + Client_keys.get_key cctxt bootstrap_account.public_key_hash + >>=? fun (name, _, sk_uri) -> + return {name; sk_uri; amount = bootstrap_account.amount} + +let parsed_account_repr_encoding = + let open Data_encoding in + conv + (fun p -> (p.name, p.sk_uri, p.amount)) + (fun (name, sk_uri, amount) -> {name; sk_uri; amount}) + (obj3 + (req "name" string) + (req "sk_uri" Client_keys.Secret_key.encoding) + (req "amount" Tez.encoding)) + +let mockup_default_bootstrap_accounts + (cctxt : Tezos_client_base.Client_context.full) : string tzresult Lwt.t = + let rpc_context = new Protocol_client_context.wrap_full cctxt in + let wallet = (cctxt :> Client_context.wallet) in + let parsed_account_reprs = ref [] in + let errors = ref [] in + Client_keys.list_keys wallet + >>=? fun all_keys -> + List.iter_s + (function + | (name, pkh, _pk_opt, Some sk_uri) -> ( + let contract = + Protocol.Alpha_context.Contract.implicit_contract pkh + in + Client_proto_context.get_balance + rpc_context + ~chain:cctxt#chain + ~block:cctxt#block + contract + >>= fun tz_balance -> + match tz_balance with + | Ok balance -> ( + let tez_repr = + Tez.of_mutez @@ Protocol.Alpha_context.Tez.to_mutez balance + in + match tez_repr with + | None -> + (* we're reading the wallet, it's content MUST be valid *) + assert false + | Some amount -> + parsed_account_reprs := + {name; sk_uri; amount} :: !parsed_account_reprs ; + Lwt.return_unit ) + | Error err -> + errors := err :: !errors ; + Lwt.return_unit ) + | _ -> + Lwt.return_unit) + all_keys + >>= fun () -> + match !errors with + | [] -> + let json = + Data_encoding.Json.construct + (Data_encoding.list parsed_account_repr_encoding) + !parsed_account_reprs + in + return @@ Data_encoding.Json.to_string json + | errs -> + Lwt.return_error @@ List.concat errs + +let protocol_constants_no_overrides = + { + hard_gas_limit_per_operation = None; + hard_gas_limit_per_block = None; + hard_storage_limit_per_operation = None; + cost_per_byte = None; + chain_id = None; + timestamp = None; + } + +let apply_protocol_overrides (cctxt : Tezos_client_base.Client_context.full) + (o : protocol_constants_overrides) (c : Constants.parametric) = + let has_custom = + Option.is_some o.hard_gas_limit_per_operation + || Option.is_some o.hard_gas_limit_per_block + || Option.is_some o.hard_storage_limit_per_operation + || Option.is_some o.cost_per_byte + || Option.is_some o.chain_id + in + ( if has_custom then + let pp_opt_custom name pp ppf opt_value = + match opt_value with + | None -> + () + | Some value -> + Format.fprintf ppf "@[%s: %a@]@," name pp value + in + cctxt#message + "@[mockup client uses protocol overrides:@,%a%a%a%a%a@]@?" + (pp_opt_custom "hard_gas_limit_per_operation" Gas.Arith.pp_integral) + o.hard_gas_limit_per_operation + (pp_opt_custom "hard_gas_limit_per_block" Gas.Arith.pp_integral) + o.hard_gas_limit_per_block + (pp_opt_custom "hard_storage_limit_per_operation" Z.pp_print) + o.hard_storage_limit_per_operation + (pp_opt_custom "cost_per_byte" Tez.pp) + o.cost_per_byte + (pp_opt_custom "chain_id" Chain_id.pp) + o.chain_id + else Lwt.return_unit ) + >>= fun () -> + return + { + c with + hard_gas_limit_per_operation = + Option.value + ~default:c.hard_gas_limit_per_operation + o.hard_gas_limit_per_operation; + hard_gas_limit_per_block = + Option.value + ~default:c.hard_gas_limit_per_block + o.hard_gas_limit_per_block; + hard_storage_limit_per_operation = + Option.value + ~default:c.hard_storage_limit_per_operation + o.hard_storage_limit_per_operation; + cost_per_byte = Option.value ~default:c.cost_per_byte o.cost_per_byte; + } + +let to_bootstrap_account repr = + Tezos_client_base.Client_keys.neuterize repr.sk_uri + >>=? fun pk_uri -> + Tezos_client_base.Client_keys.public_key pk_uri + >>=? fun public_key -> + let public_key_hash = Signature.Public_key.hash public_key in + return + Parameters. + {public_key_hash; public_key = Some public_key; amount = repr.amount} + +(* ------------------------------------------------------------------------- *) +(* Blocks *) + +type block = { + hash : Block_hash.t; + header : Protocol.Alpha_context.Block_header.t; + operations : Protocol.Alpha_context.Operation.packed list; + context : Protocol.Environment.Context.t; +} + +module Forge = struct + let default_proof_of_work_nonce = + Bytes.create Protocol.Alpha_context.Constants.proof_of_work_nonce_size + + let make_shell ~level ~predecessor ~timestamp ~fitness ~operations_hash = + Tezos_base.Block_header. + { + level; + predecessor; + timestamp; + fitness; + operations_hash; + proto_level = 0; + validation_passes = 0; + context = Context_hash.zero; + } +end + +(* ------------------------------------------------------------------------- *) +(* RPC context *) + +let initial_context (header : Block_header.shell_header) + (params : mockup_protocol_parameters) = + let parameters = + Default_parameters.parameters_of_constants + ~bootstrap_accounts:params.bootstrap_accounts + ~bootstrap_contracts:params.bootstrap_contracts + ~with_commitments:false + params.constants + in + let json = Default_parameters.json_of_parameters parameters in + let proto_params = + Data_encoding.Binary.to_bytes_exn Data_encoding.json json + in + Tezos_protocol_environment.Context.( + let empty = Memory_context.empty in + add empty ["version"] (Bytes.of_string "genesis") + >>= fun ctxt -> add ctxt ["protocol_parameters"] proto_params) + >>= fun ctxt -> + Protocol.Main.init ctxt header + >|= Protocol.Environment.wrap_tzresult + >>=? fun {context; _} -> return context + +let mem_init : + cctxt:Tezos_client_base.Client_context.full -> + parameters:mockup_protocol_parameters -> + constants_overrides_json:Data_encoding.json option -> + bootstrap_accounts_json:Data_encoding.json option -> + (Chain_id.t * Tezos_protocol_environment.rpc_context) tzresult Lwt.t = + fun ~cctxt ~parameters ~constants_overrides_json ~bootstrap_accounts_json -> + let hash = + Block_hash.of_b58check_exn + "BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU" + in + (* Need to read this Json file before since timestamp modification may be in + there *) + ( match constants_overrides_json with + | None -> + return protocol_constants_no_overrides + | Some json -> ( + match + Data_encoding.Json.destruct protocol_constants_overrides_encoding json + with + | x -> + return x + | exception error -> + failwith + "cannot read protocol constants overrides: %a" + (Data_encoding.Json.print_error ?print_unknown:None) + error ) ) + >>=? fun protocol_overrides -> + let default = parameters.initial_timestamp in + let timestamp = Option.value ~default protocol_overrides.timestamp in + ( if not @@ Time.Protocol.equal default timestamp then + cctxt#message "@[initial_timestamp: %a@]" Time.Protocol.pp_hum timestamp + else Lwt.return_unit ) + >>= fun () -> + let shell = + Forge.make_shell + ~level:0l + ~predecessor:hash + ~timestamp + ~fitness:(Fitness.from_int64 0L) + ~operations_hash:Operation_list_list_hash.zero + in + apply_protocol_overrides cctxt protocol_overrides parameters.constants + >>=? fun protocol_custom -> + ( match bootstrap_accounts_json with + | None -> + return None + | Some json -> ( + match + Data_encoding.Json.destruct + (Data_encoding.list parsed_account_repr_encoding) + json + with + | accounts -> + cctxt#message "@[mockup client uses custom bootstrap accounts:@]" + >>= fun () -> + let open Format in + cctxt#message + "@[%a@]" + (pp_print_list + ~pp_sep:(fun ppf () -> fprintf ppf ";@ ") + parsed_account_repr_pp) + accounts + >>= fun () -> + List.map_es to_bootstrap_account accounts + >>=? fun bootstrap_accounts -> return (Some bootstrap_accounts) + | exception error -> + failwith + "cannot read definitions of bootstrap accounts: %a" + (Data_encoding.Json.print_error ?print_unknown:None) + error ) ) + >>=? fun bootstrap_accounts_custom -> + initial_context + shell + { + parameters with + bootstrap_accounts = + Option.value + ~default:parameters.bootstrap_accounts + bootstrap_accounts_custom; + constants = protocol_custom; + } + >>=? fun context -> + let chain_id = + Tezos_mockup_registration.Mockup_args.Chain_id.choose + ~from_config_file:protocol_overrides.chain_id + in + return + ( chain_id, + { + Tezos_protocol_environment.block_hash = hash; + block_header = shell; + context; + } ) + +let migrate : + Chain_id.t * Tezos_protocol_environment.rpc_context -> + (Chain_id.t * Tezos_protocol_environment.rpc_context) tzresult Lwt.t = + fun (chain_id, rpc_context) -> + let {Tezos_protocol_environment.block_hash; context; block_header} = + rpc_context + in + Protocol.Main.init context block_header + >|= Protocol.Environment.wrap_tzresult + >>=? fun {context; _} -> + let rpc_context = + {Tezos_protocol_environment.block_hash; block_header; context} + in + return (chain_id, rpc_context) + +(* ------------------------------------------------------------------------- *) +(* Register mockup *) + +let () = + let open Tezos_mockup_registration.Registration in + let module M : MOCKUP = struct + type parameters = mockup_protocol_parameters + + type protocol_constants = protocol_constants_overrides + + let parameters_encoding = mockup_protocol_parameters_encoding + + let protocol_constants_encoding = protocol_constants_overrides_encoding + + let default_bootstrap_accounts = mockup_default_bootstrap_accounts + + let default_parameters = default_mockup_parameters + + let default_protocol_constants = default_mockup_protocol_constants + + let protocol_hash = Protocol.hash + + module Protocol = Protocol_client_context.Lifted_protocol + module Block_services = Protocol_client_context.Alpha_block_services + + let directory = Plugin.RPC.rpc_services + + let init = mem_init + + let migrate = migrate + end in + register_mockup_environment (module M) diff --git a/src/proto_009_PsFLoren/lib_client/operation_result.ml b/src/proto_009_PsFLoren/lib_client/operation_result.ml new file mode 100644 index 0000000000000000000000000000000000000000..80370e7c9d6ff34965ef83f07be995b90eabb577 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/operation_result.ml @@ -0,0 +1,539 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Apply_results + +let pp_manager_operation_content (type kind) source internal pp_result ppf + ((operation, result) : kind manager_operation * _) = + Format.fprintf ppf "@[" ; + ( match operation with + | Transaction {destination; amount; parameters; entrypoint} -> + Format.fprintf + ppf + "@[%s:@,Amount: %s%a@,From: %a@,To: %a" + (if internal then "Internal transaction" else "Transaction") + Client_proto_args.tez_sym + Tez.pp + amount + Contract.pp + source + Contract.pp + destination ; + ( match entrypoint with + | "default" -> + () + | _ -> + Format.fprintf ppf "@,Entrypoint: %s" entrypoint ) ; + ( if not (Script_repr.is_unit_parameter parameters) then + let expr = + WithExceptions.Option.to_exn + ~none:(Failure "ill-serialized argument") + (Data_encoding.force_decode parameters) + in + Format.fprintf + ppf + "@,Parameter: @[%a@]" + Michelson_v1_printer.print_expr + expr ) ; + pp_result ppf result ; Format.fprintf ppf "@]" + | Origination {delegate; credit; script = {code; storage}; preorigination = _} + -> + Format.fprintf + ppf + "@[%s:@,From: %a@,Credit: %s%a" + (if internal then "Internal origination" else "Origination") + Contract.pp + source + Client_proto_args.tez_sym + Tez.pp + credit ; + let code = + WithExceptions.Option.to_exn + ~none:(Failure "ill-serialized code") + (Data_encoding.force_decode code) + and storage = + WithExceptions.Option.to_exn + ~none:(Failure "ill-serialized storage") + (Data_encoding.force_decode storage) + in + let {Michelson_v1_parser.source; _} = + Michelson_v1_printer.unparse_toplevel code + in + Format.fprintf + ppf + "@,@[Script:@ @[%a@]@,@[Initial storage:@ %a@]" + Format.pp_print_text + source + Michelson_v1_printer.print_expr + storage ; + ( match delegate with + | None -> + Format.fprintf ppf "@,No delegate for this contract" + | Some delegate -> + Format.fprintf + ppf + "@,Delegate: %a" + Signature.Public_key_hash.pp + delegate ) ; + pp_result ppf result ; Format.fprintf ppf "@]" + | Reveal key -> + Format.fprintf + ppf + "@[%s of manager public key:@,Contract: %a@,Key: %a%a@]" + (if internal then "Internal revelation" else "Revelation") + Contract.pp + source + Signature.Public_key.pp + key + pp_result + result + | Delegation None -> + Format.fprintf + ppf + "@[%s:@,Contract: %a@,To: nobody%a@]" + (if internal then "Internal Delegation" else "Delegation") + Contract.pp + source + pp_result + result + | Delegation (Some delegate) -> + Format.fprintf + ppf + "@[%s:@,Contract: %a@,To: %a%a@]" + (if internal then "Internal Delegation" else "Delegation") + Contract.pp + source + Signature.Public_key_hash.pp + delegate + pp_result + result ) ; + Format.fprintf ppf "@]" + +let pp_balance_updates ppf = function + | [] -> + () + | balance_updates -> + let open Receipt in + (* For dry runs, the baker's key is zero + (tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU). Instead of printing this + key hash, we want to make the result more informative. *) + let pp_baker ppf baker = + if Signature.Public_key_hash.equal baker Signature.Public_key_hash.zero + then Format.fprintf ppf "the baker who will include this operation" + else Signature.Public_key_hash.pp ppf baker + in + let balance_updates = + List.map + (fun (balance, update, origin) -> + let balance = + match balance with + | Contract c -> + Format.asprintf "%a" Contract.pp c + | Rewards (pkh, l) -> + Format.asprintf "rewards(%a,%a)" pp_baker pkh Cycle.pp l + | Fees (pkh, l) -> + Format.asprintf "fees(%a,%a)" pp_baker pkh Cycle.pp l + | Deposits (pkh, l) -> + Format.asprintf "deposits(%a,%a)" pp_baker pkh Cycle.pp l + in + let balance = + match origin with + | Block_application -> + balance + | Protocol_migration -> + Format.asprintf "migration %s" balance + in + (balance, update)) + balance_updates + in + let column_size = + List.fold_left + (fun acc (balance, _) -> Compare.Int.max acc (String.length balance)) + 0 + balance_updates + in + let pp_update ppf = function + | Credited amount -> + Format.fprintf ppf "+%s%a" Client_proto_args.tez_sym Tez.pp amount + | Debited amount -> + Format.fprintf ppf "-%s%a" Client_proto_args.tez_sym Tez.pp amount + in + let pp_one ppf (balance, update) = + let to_fill = column_size + 3 - String.length balance in + let filler = String.make to_fill '.' in + Format.fprintf ppf "%s %s %a" balance filler pp_update update + in + Format.fprintf + ppf + "@[%a@]" + (Format.pp_print_list pp_one) + balance_updates + +let pp_manager_operation_contents_and_result ppf + ( Manager_operation + {source; fee; operation; counter; gas_limit; storage_limit}, + Manager_operation_result + {balance_updates; operation_result; internal_operation_results} ) = + let pp_lazy_storage_diff = function + | None -> + () + | Some lazy_storage_diff -> ( + let big_map_diff = + Contract.Legacy_big_map_diff.of_lazy_storage_diff lazy_storage_diff + in + match (big_map_diff :> Contract.Legacy_big_map_diff.item list) with + | [] -> + () + | _ :: _ -> + (* TODO: print all lazy storage diff *) + Format.fprintf + ppf + "@,@[Updated big_maps:@ %a@]" + Michelson_v1_printer.print_big_map_diff + lazy_storage_diff ) + in + let pp_transaction_result + (Transaction_result + { balance_updates; + consumed_gas; + storage; + originated_contracts; + storage_size; + paid_storage_size_diff; + lazy_storage_diff; + allocated_destination_contract = _ }) = + ( match originated_contracts with + | [] -> + () + | contracts -> + Format.fprintf + ppf + "@,@[Originated contracts:@,%a@]" + (Format.pp_print_list Contract.pp) + contracts ) ; + ( match storage with + | None -> + () + | Some expr -> + Format.fprintf + ppf + "@,@[Updated storage:@ %a@]" + Michelson_v1_printer.print_expr + expr ) ; + pp_lazy_storage_diff lazy_storage_diff ; + if storage_size <> Z.zero then + Format.fprintf ppf "@,Storage size: %s bytes" (Z.to_string storage_size) ; + if paid_storage_size_diff <> Z.zero then + Format.fprintf + ppf + "@,Paid storage size diff: %s bytes" + (Z.to_string paid_storage_size_diff) ; + Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas ; + match balance_updates with + | [] -> + () + | balance_updates -> + Format.fprintf + ppf + "@,Balance updates:@, %a" + pp_balance_updates + balance_updates + in + let pp_origination_result + (Origination_result + { lazy_storage_diff; + balance_updates; + consumed_gas; + originated_contracts; + storage_size; + paid_storage_size_diff }) = + ( match originated_contracts with + | [] -> + () + | contracts -> + Format.fprintf + ppf + "@,@[Originated contracts:@,%a@]" + (Format.pp_print_list Contract.pp) + contracts ) ; + if storage_size <> Z.zero then + Format.fprintf ppf "@,Storage size: %s bytes" (Z.to_string storage_size) ; + pp_lazy_storage_diff lazy_storage_diff ; + if paid_storage_size_diff <> Z.zero then + Format.fprintf + ppf + "@,Paid storage size diff: %s bytes" + (Z.to_string paid_storage_size_diff) ; + Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas ; + match balance_updates with + | [] -> + () + | balance_updates -> + Format.fprintf + ppf + "@,Balance updates:@, %a" + pp_balance_updates + balance_updates + in + let pp_result (type kind) ppf (result : kind manager_operation_result) = + Format.fprintf ppf "@," ; + match result with + | Skipped _ -> + Format.fprintf ppf "This operation was skipped" + | Failed (_, _errs) -> + Format.fprintf ppf "This operation FAILED." + | Applied (Reveal_result {consumed_gas}) -> + Format.fprintf ppf "This revelation was successfully applied" ; + Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas + | Backtracked (Reveal_result _, _) -> + Format.fprintf + ppf + "@[This revelation was BACKTRACKED, its expected effects were \ + NOT applied.@]" + | Applied (Delegation_result {consumed_gas}) -> + Format.fprintf ppf "This delegation was successfully applied" ; + Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas + | Backtracked (Delegation_result _, _) -> + Format.fprintf + ppf + "@[This delegation was BACKTRACKED, its expected effects were \ + NOT applied.@]" + | Applied (Transaction_result _ as tx) -> + Format.fprintf ppf "This transaction was successfully applied" ; + pp_transaction_result tx + | Backtracked ((Transaction_result _ as tx), _errs) -> + Format.fprintf + ppf + "@[This transaction was BACKTRACKED, its expected effects (as \ + follow) were NOT applied.@]" ; + pp_transaction_result tx + | Applied (Origination_result _ as op) -> + Format.fprintf ppf "This origination was successfully applied" ; + pp_origination_result op + | Backtracked ((Origination_result _ as op), _errs) -> + Format.fprintf + ppf + "@[This origination was BACKTRACKED, its expected effects (as \ + follow) were NOT applied.@]" ; + pp_origination_result op + in + Format.fprintf + ppf + "@[@[Manager signed operations:@,\ + From: %a@,\ + Fee to the baker: %s%a@,\ + Expected counter: %s@,\ + Gas limit: %a@,\ + Storage limit: %s bytes" + Signature.Public_key_hash.pp + source + Client_proto_args.tez_sym + Tez.pp + fee + (Z.to_string counter) + Gas.Arith.pp_integral + gas_limit + (Z.to_string storage_limit) ; + ( match balance_updates with + | [] -> + () + | balance_updates -> + Format.fprintf + ppf + "@,Balance updates:@, %a" + pp_balance_updates + balance_updates ) ; + Format.fprintf + ppf + "@,%a" + (pp_manager_operation_content + (Contract.implicit_contract source) + false + pp_result) + (operation, operation_result) ; + ( match internal_operation_results with + | [] -> + () + | _ :: _ -> + Format.fprintf + ppf + "@,@[Internal operations:@ %a@]" + (Format.pp_print_list (fun ppf (Internal_operation_result (op, res)) -> + pp_manager_operation_content + op.source + false + pp_result + ppf + (op.operation, res))) + internal_operation_results ) ; + Format.fprintf ppf "@]" + +let rec pp_contents_and_result_list : + type kind. Format.formatter -> kind contents_and_result_list -> unit = + fun ppf -> function + | Single_and_result + (Seed_nonce_revelation {level; nonce}, Seed_nonce_revelation_result bus) + -> + Format.fprintf + ppf + "@[Seed nonce revelation:@,\ + Level: %a@,\ + Nonce (hash): %a@,\ + Balance updates:@,\ + \ %a@]" + Raw_level.pp + level + Nonce_hash.pp + (Nonce.hash nonce) + pp_balance_updates + bus + | Single_and_result + (Double_baking_evidence {bh1; bh2}, Double_baking_evidence_result bus) -> + Format.fprintf + ppf + "@[Double baking evidence:@,\ + Exhibit A: %a@,\ + Exhibit B: %a@,\ + Balance updates:@,\ + \ %a@]" + Block_hash.pp + (Block_header.hash bh1) + Block_hash.pp + (Block_header.hash bh2) + pp_balance_updates + bus + | Single_and_result + ( Double_endorsement_evidence {op1; op2; slot = _}, + Double_endorsement_evidence_result bus ) -> + Format.fprintf + ppf + "@[Double endorsement evidence:@,\ + Exhibit A: %a@,\ + Exhibit B: %a@,\ + Balance updates:@,\ + \ %a@]" + Operation_hash.pp + (Operation.hash op1) + Operation_hash.pp + (Operation.hash op2) + pp_balance_updates + bus + | Single_and_result (Activate_account {id; _}, Activate_account_result bus) + -> + Format.fprintf + ppf + "@[Genesis account activation:@,\ + Account: %a@,\ + Balance updates:@,\ + \ %a@]" + Ed25519.Public_key_hash.pp + id + pp_balance_updates + bus + | Single_and_result + ( Endorsement_with_slot + { endorsement = + {protocol_data = {contents = Single (Endorsement {level}); _}; _}; + _ }, + Endorsement_with_slot_result + (Endorsement_result {balance_updates; delegate; slots}) ) + | Single_and_result + ( Endorsement {level}, + Endorsement_result {balance_updates; delegate; slots} ) -> + Format.fprintf + ppf + "@[Endorsement:@,\ + Level: %a@,\ + Balance updates:%a@,\ + Delegate: %a@,\ + Slots: %a@]" + Raw_level.pp + level + pp_balance_updates + balance_updates + Signature.Public_key_hash.pp + delegate + (Format.pp_print_list ~pp_sep:Format.pp_print_space Format.pp_print_int) + slots + | Single_and_result (Proposals {source; period; proposals}, Proposals_result) + -> + Format.fprintf + ppf + "@[Proposals:@,\ + From: %a@,\ + Period: %ld@,\ + Protocols:@,\ + \ @[%a@]@]" + Signature.Public_key_hash.pp + source + period + (Format.pp_print_list Protocol_hash.pp) + proposals + | Single_and_result (Ballot {source; period; proposal; ballot}, Ballot_result) + -> + Format.fprintf + ppf + "@[Ballot:@,From: %a@,Period: %ld@,Protocol: %a@,Vote: %a@]" + Signature.Public_key_hash.pp + source + period + Protocol_hash.pp + proposal + Data_encoding.Json.pp + (Data_encoding.Json.construct Vote.ballot_encoding ballot) + | Single_and_result (Failing_noop _arbitrary, _) -> + (* the Failing_noop operation always fails and can't have result *) + . + | Single_and_result + ((Manager_operation _ as op), (Manager_operation_result _ as res)) -> + Format.fprintf ppf "%a" pp_manager_operation_contents_and_result (op, res) + | Cons_and_result + ((Manager_operation _ as op), (Manager_operation_result _ as res), rest) + -> + Format.fprintf + ppf + "%a@\n%a" + pp_manager_operation_contents_and_result + (op, res) + pp_contents_and_result_list + rest + +let pp_operation_result ppf + ((op, res) : 'kind contents_list * 'kind contents_result_list) = + Format.fprintf ppf "@[" ; + let contents_and_result_list = Apply_results.pack_contents_list op res in + pp_contents_and_result_list ppf contents_and_result_list ; + Format.fprintf ppf "@]@." + +let pp_internal_operation ppf + (Internal_operation {source; operation; nonce = _}) = + pp_manager_operation_content + source + true + (fun _ppf () -> ()) + ppf + (operation, ()) diff --git a/src/proto_009_PsFLoren/lib_client/operation_result.mli b/src/proto_009_PsFLoren/lib_client/operation_result.mli new file mode 100644 index 0000000000000000000000000000000000000000..cc03abfcd36b557649a201ff65bf21831488fbd0 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/operation_result.mli @@ -0,0 +1,35 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +val pp_internal_operation : + Format.formatter -> packed_internal_operation -> unit + +val pp_operation_result : + Format.formatter -> + 'kind contents_list * 'kind Apply_results.contents_result_list -> + unit diff --git a/src/proto_009_PsFLoren/lib_client/protocol_client_context.ml b/src/proto_009_PsFLoren/lib_client/protocol_client_context.ml new file mode 100644 index 0000000000000000000000000000000000000000..25db3938e2069cbc743c311a90e813d30eb263e2 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/protocol_client_context.ml @@ -0,0 +1,259 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Lifted_protocol = struct + include Protocol.Environment.Lift (Protocol) + + let hash = Protocol.hash +end + +module Alpha_block_services = + Block_services.Make (Lifted_protocol) (Lifted_protocol) + +(** Client RPC context *) + +class type rpc_context = + object + inherit RPC_context.json + + inherit + [Shell_services.chain * Shell_services.block] Protocol.Environment + .RPC_context + .simple + end + +class wrap_rpc_context (t : RPC_context.json) : rpc_context = + object + method base : Uri.t = t#base + + method generic_json_call = t#generic_json_call + + method call_service + : 'm 'p 'q 'i 'o. + (([< Resto.meth] as 'm), unit, 'p, 'q, 'i, 'o) RPC_service.t -> 'p -> + 'q -> 'i -> 'o tzresult Lwt.t = + t#call_service + + method call_streamed_service + : 'm 'p 'q 'i 'o. + (([< Resto.meth] as 'm), unit, 'p, 'q, 'i, 'o) RPC_service.t -> + on_chunk:('o -> unit) -> on_close:(unit -> unit) -> 'p -> 'q -> 'i -> + (unit -> unit) tzresult Lwt.t = + t#call_streamed_service + + inherit + [Shell_services.chain, Shell_services.block] Protocol.Environment + .proto_rpc_context + (t :> RPC_context.t) + Shell_services.Blocks.path + end + +class type full = + object + inherit Client_context.full + + inherit + [Shell_services.chain * Shell_services.block] Protocol.Environment + .RPC_context + .simple + + inherit + [Shell_services.chain, Shell_services.block] Protocol.Environment + .proto_rpc_context + end + +class wrap_full (t : Client_context.full) : full = + object + inherit Client_context.proxy_context t + + inherit + [Shell_services.chain, Shell_services.block] Protocol.Environment + .proto_rpc_context + (t :> RPC_context.t) + Shell_services.Blocks.path + end + +let register_error_kind category ~id ~title ~description ?pp encoding + from_error to_error = + let id = "client." ^ Protocol.name ^ "." ^ id in + register_error_kind + category + ~id + ~title + ~description + ?pp + encoding + from_error + to_error + +let () = + let open Data_encoding.Registration in + register Protocol.Alpha_context.Lazy_storage.encoding ; + (* These encodings are missing a def field which we add before registering them. + These defs should be moved inside their encodings in the protocol code. *) + let def id ids ?title ?description encoding = + Data_encoding.def + (String.concat "." (Protocol.name :: id :: ids)) + ?title + ?description + encoding + in + register @@ def "parameters" [] Protocol.Parameters_repr.encoding ; + register ~pp:Protocol.Alpha_context.Tez.pp + @@ def "tez" [] Protocol.Alpha_context.Tez.encoding ; + register @@ def "roll" [] Protocol.Alpha_context.Roll.encoding ; + register ~pp:Protocol.Alpha_context.Fitness.pp + @@ def "fitness" [] Protocol.Alpha_context.Fitness.encoding ; + register ~pp:Protocol.Alpha_context.Timestamp.pp + @@ def "timestamp" [] Protocol.Alpha_context.Timestamp.encoding ; + register ~pp:Protocol.Alpha_context.Raw_level.pp + @@ def "raw_level" [] Protocol.Alpha_context.Raw_level.encoding ; + register @@ def "vote" ["ballot"] Protocol.Alpha_context.Vote.ballot_encoding ; + register + @@ def "vote" ["ballots"] Protocol.Alpha_context.Vote.ballots_encoding ; + register + @@ def "vote" ["listings"] Protocol.Alpha_context.Vote.listings_encoding ; + register @@ def "seed" [] Protocol.Alpha_context.Seed.seed_encoding ; + register ~pp:Protocol.Alpha_context.Gas.pp + @@ def "gas" [] Protocol.Alpha_context.Gas.encoding ; + register ~pp:Protocol.Alpha_context.Gas.pp_cost + @@ def "gas" ["cost"] Protocol.Alpha_context.Gas.cost_encoding ; + register @@ def "script" [] Protocol.Alpha_context.Script.encoding ; + register @@ def "script" ["expr"] Protocol.Alpha_context.Script.expr_encoding ; + register @@ def "script" ["prim"] Protocol.Alpha_context.Script.prim_encoding ; + register + @@ def + "script" + ["lazy_expr"] + Protocol.Alpha_context.Script.lazy_expr_encoding ; + register + @@ def "script" ["loc"] Protocol.Alpha_context.Script.location_encoding ; + register ~pp:Protocol.Alpha_context.Contract.pp + @@ def "contract" [] Protocol.Alpha_context.Contract.encoding ; + register + @@ def + "contract" + ["big_map_diff"] + Protocol.Alpha_context.Lazy_storage.legacy_big_map_diff_encoding ; + register + @@ def + "delegate" + ["frozen_balance"] + Protocol.Alpha_context.Delegate.frozen_balance_encoding ; + register + @@ def + "delegate" + ["frozen_balance_by_cycles"] + Protocol.Alpha_context.Delegate.frozen_balance_by_cycle_encoding ; + register + @@ def + "receipt" + ["balance_updates"] + Protocol.Alpha_context.Receipt.balance_updates_encoding ; + register ~pp:Protocol.Alpha_context.Level.pp_full + @@ def "level" [] Protocol.Alpha_context.Level.encoding ; + register @@ def "operation" [] Protocol.Alpha_context.Operation.encoding ; + register + @@ def + "operation" + ["contents"] + Protocol.Alpha_context.Operation.contents_encoding ; + register + @@ def + "operation" + ["contents_list"] + Protocol.Alpha_context.Operation.contents_list_encoding ; + register + @@ def + "operation" + ["protocol_data"] + Protocol.Alpha_context.Operation.protocol_data_encoding ; + register + @@ def "operation" ["raw"] Protocol.Alpha_context.Operation.raw_encoding ; + register + @@ def + "operation" + ["internal"] + Protocol.Alpha_context.Operation.internal_operation_encoding ; + register + @@ def + "operation" + ["unsigned"] + Protocol.Alpha_context.Operation.unsigned_encoding ; + register ~pp:Protocol.Alpha_context.Period.pp + @@ def "period" [] Protocol.Alpha_context.Period.encoding ; + register ~pp:Protocol.Alpha_context.Cycle.pp + @@ def "cycle" [] Protocol.Alpha_context.Cycle.encoding ; + register @@ def "constants" [] Protocol.Alpha_context.Constants.encoding ; + register + @@ def "constants" ["fixed"] Protocol.Alpha_context.Constants.fixed_encoding ; + register + @@ def + "constants" + ["parametric"] + Protocol.Alpha_context.Constants.parametric_encoding ; + register @@ def "nonce" [] Protocol.Alpha_context.Nonce.encoding ; + register + @@ def "block_header" [] Protocol.Alpha_context.Block_header.encoding ; + register + @@ def + "block_header" + ["unsigned"] + Protocol.Alpha_context.Block_header.unsigned_encoding ; + register + @@ def + "block_header" + ["raw"] + Protocol.Alpha_context.Block_header.raw_encoding ; + register + @@ def + "block_header" + ["contents"] + Protocol.Alpha_context.Block_header.contents_encoding ; + register + @@ def + "block_header" + ["shell_header"] + Protocol.Alpha_context.Block_header.shell_header_encoding ; + register + @@ def + "block_header" + ["protocol_data"] + Protocol.Alpha_context.Block_header.protocol_data_encoding ; + register ~pp:Protocol.Alpha_context.Voting_period.pp + @@ def "voting_period" [] Protocol.Alpha_context.Voting_period.encoding ; + register + @@ def + "voting_period" + ["kind"] + Protocol.Alpha_context.Voting_period.kind_encoding ; + register + @@ def + "errors" + [] + ~description: + "The full list of RPC errors would be too long to include.It is\n\ + available through the RPC `/errors` (GET)." + error_encoding diff --git a/src/proto_009_PsFLoren/lib_client/proxy.ml b/src/proto_009_PsFLoren/lib_client/proxy.ml new file mode 100644 index 0000000000000000000000000000000000000000..2caa499ef5ab0dc6b289e2eff5f1b09d0c3c6df1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/proxy.ml @@ -0,0 +1,140 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module L = ( val Tezos_proxy.Logger.logger ~protocol_name:Protocol.name + : Tezos_proxy.Logger.S ) + +let proxy_block_header (rpc_context : RPC_context.json) + (chain : Tezos_shell_services.Block_services.chain) + (block : Tezos_shell_services.Block_services.block) = + let rpc_context = new Protocol_client_context.wrap_rpc_context rpc_context in + L.emit + L.proxy_block_header + ( Tezos_shell_services.Block_services.chain_to_string chain, + Tezos_shell_services.Block_services.to_string block ) + >>= fun () -> + Protocol_client_context.Alpha_block_services.header + rpc_context + ~chain + ~block + () + +module ProtoRpc : Tezos_proxy.Proxy_proto.PROTO_RPC = struct + let split_key (key : Proxy_context.M.key) : + (Proxy_context.M.key * Proxy_context.M.key) option = + match key with + (* matches paths like: + contracts/index/05/37/bc/fb/1e/39/000002298c03ed7d454a101eb7022bc95f7e5f41ac78/tail *) + | "contracts" + :: index + :: hash0 :: hash1 :: hash2 :: hash3 :: hash4 :: hash5 :: id :: tail -> + Some + ( ["contracts"; index; hash0; hash1; hash2; hash3; hash4; hash5; id], + tail ) + | "cycle" :: i :: tail -> + Some (["cycle"; i], tail) + (* matches paths like: + rolls/owner/snapshot/19/1/tail *) + | "rolls" :: "owner" :: "snapshot" :: i :: j :: tail -> + Some (["rolls"; "owner"; "snapshot"; i; j], tail) + | "v1" :: tail -> + Some (["v1"], tail) + | _ -> + None + + let do_rpc (pgi : Tezos_proxy.Proxy.proxy_getter_input) + (key : Proxy_context.M.key) = + let chain = pgi.chain in + let block = pgi.block in + L.emit + L.proxy_block_rpc + ( Tezos_shell_services.Block_services.chain_to_string chain, + Tezos_shell_services.Block_services.to_string block, + key ) + >>= fun () -> + Protocol_client_context.Alpha_block_services.Context.read + pgi.rpc_context + ~chain + ~block + key + >>=? fun (raw_context : Block_services.raw_context) -> + L.emit L.tree_received + @@ Int64.of_int (Tezos_proxy.Proxy_getter.raw_context_size raw_context) + >>= fun () -> return raw_context +end + +let initial_context (rpc_context : RPC_context.json) + (chain : Tezos_shell_services.Block_services.chain) + (block : Tezos_shell_services.Block_services.block) : + Environment_context.Context.t Lwt.t = + let module M = Tezos_proxy.Proxy_getter.MakeProxy (ProtoRpc) in + L.emit + L.proxy_getter_created + ( Tezos_shell_services.Block_services.chain_to_string chain, + Tezos_shell_services.Block_services.to_string block ) + >>= fun () -> + let pgi : Tezos_proxy.Proxy.proxy_getter_input = + {rpc_context = (rpc_context :> RPC_context.simple); chain; block} + in + let module N : Proxy_context.M.ProxyDelegate = struct + let proxy_dir_mem = M.proxy_dir_mem pgi + + let proxy_get = M.proxy_get pgi + + let proxy_mem = M.proxy_mem pgi + end in + let empty = Proxy_context.empty @@ Some (module N) in + let version_value = "florence_009" in + Tezos_protocol_environment.Context.add + empty + ["version"] + (Bytes.of_string version_value) + +let init_env_rpc_context (_printer : Tezos_client_base.Client_context.printer) + (rpc_context : RPC_context.json) + (chain : Tezos_shell_services.Block_services.chain) + (block : Tezos_shell_services.Block_services.block) : + Tezos_protocol_environment.rpc_context tzresult Lwt.t = + proxy_block_header rpc_context chain block + >>=? fun {shell; hash; _} -> + let block_hash = hash in + initial_context rpc_context chain block + >>= fun context -> + return {Tezos_protocol_environment.block_hash; block_header = shell; context} + +let () = + let open Tezos_proxy.Registration in + let module M : Proxy_sig = struct + module Protocol = Protocol_client_context.Lifted_protocol + + let protocol_hash = Protocol.hash + + let directory = Plugin.RPC.rpc_services + + let hash = Protocol_client_context.Alpha_block_services.hash + + let init_env_rpc_context = init_env_rpc_context + end in + register_proxy_context (module M) diff --git a/src/proto_009_PsFLoren/lib_client/test/.ocamlformat b/src/proto_009_PsFLoren/lib_client/test/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/test/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_client/test/assert.ml b/src/proto_009_PsFLoren/lib_client/test/assert.ml new file mode 100644 index 0000000000000000000000000000000000000000..3d414c2eafa9ceea09aedcfe3e850a21ef925c11 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/test/assert.ml @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let fail expected given msg = + Format.kasprintf + Stdlib.failwith + "@[%s@ expected: %s@ got: %s@]" + msg + expected + given + +let default_printer _ = "" + +let equal ?(eq = ( = )) ?(print = default_printer) ?(msg = "") x y = + if not (eq x y) then fail (print x) (print y) msg diff --git a/src/proto_009_PsFLoren/lib_client/test/dune b/src/proto_009_PsFLoren/lib_client/test/dune new file mode 100644 index 0000000000000000000000000000000000000000..fff07d28ef590aff1f0ebd6989762fb7496c5cf9 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/test/dune @@ -0,0 +1,32 @@ +(executables + (names test_michelson_v1_macros) + (libraries tezos-base + tezos-micheline + tezos-protocol-009-PsFLoren + tezos-client-009-PsFLoren + alcotest-lwt) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_micheline + -open Tezos_client_009_PsFLoren + -open Tezos_protocol_009_PsFLoren))) + + +(rule +(alias buildtest) +(deps test_michelson_v1_macros.exe) +(action (progn))) + +(rule +(alias runtest_michelson_v1_macros) +(action (run %{exe:test_michelson_v1_macros.exe}))) + +(rule +(alias runtest) +(package tezos-client-009-PsFLoren) +(deps (alias runtest_michelson_v1_macros)) +(action (progn))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/lib_client/test/test_michelson_v1_macros.ml b/src/proto_009_PsFLoren/lib_client/test/test_michelson_v1_macros.ml new file mode 100644 index 0000000000000000000000000000000000000000..32c87cc8afdd401af05206841e97eb53ac5b77ee --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/test/test_michelson_v1_macros.ml @@ -0,0 +1,1295 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Client + Invocation: dune build @src/proto_alpha/lib_client/runtest + Dependencies: src/proto_alpha/lib_client/test/assert.ml + Subject: Expansion and unexpansion of Micheline terms. +*) + +open Protocol + +let print expr : string = + expr + |> Micheline_printer.printable (fun s -> s) + |> Format.asprintf "%a" Micheline_printer.print_expr + +(* expands : expression with macros fully expanded *) + +let assert_expands + (original : (Micheline_parser.location, string) Micheline.node) + (expanded : (Micheline_parser.location, string) Micheline.node) = + let ({Michelson_v1_parser.expanded = expansion; _}, errors) = + let source = print (Micheline.strip_locations original) in + Michelson_v1_parser.expand_all ~source ~original + in + match errors with + | [] -> + Assert.equal + ~print + (Michelson_v1_primitives.strings_of_prims expansion) + (Micheline.strip_locations expanded) ; + ok () + | errors -> + Error errors + +(****************************************************************************) + +open Micheline + +let zero_loc = Micheline_parser.location_zero + +let left_branch = Seq (zero_loc, [Prim (zero_loc, "SWAP", [], [])]) + +let right_branch = Seq (zero_loc, []) + +(***************************************************************************) +(* Test expands *) +(***************************************************************************) + +(** [prim_name] is the syntactic sugar to be expanded, while [compare_name] + is syntactic atom. *) +let assert_compare_macro prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "COMPARE", [], []); + Prim (zero_loc, compare_name, [], []) ] )) + +(** Expand "COMP{EQ|NEQ|LT|GT|LE|GE}" + into "COMPARE ; {EQ|NEQ|LT|GT|LE|GE}". +*) +let test_compare_marco_expansion () = + assert_compare_macro "CMPEQ" "EQ" + >>? fun () -> + assert_compare_macro "CMPNEQ" "NEQ" + >>? fun () -> + assert_compare_macro "CMPLT" "LT" + >>? fun () -> + assert_compare_macro "CMPGT" "GT" + >>? fun () -> + assert_compare_macro "CMPLE" "LE" + >>? fun () -> assert_compare_macro "CMPGE" "GE" + +let assert_if_macro prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [left_branch; right_branch], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, compare_name, [], []); + Prim (zero_loc, "IF", [left_branch; right_branch], []) ] )) + +(** Expand "IF{EQ|NEQ|LT|GT|LE|GE}" + into "{EQ|NEQ|LT|GT|LE|GE} ; IF" +*) +let test_if_compare_macros_expansion () = + assert_if_macro "IFEQ" "EQ" + >>? fun () -> + assert_if_macro "IFNEQ" "NEQ" + >>? fun () -> + assert_if_macro "IFLT" "LT" + >>? fun () -> + assert_if_macro "IFGT" "GT" + >>? fun () -> + assert_if_macro "IFLE" "LE" >>? fun () -> assert_if_macro "IFGE" "GE" + +let assert_if_cmp_macros prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [left_branch; right_branch], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "COMPARE", [], []); + Prim (zero_loc, compare_name, [], []); + Prim (zero_loc, "IF", [left_branch; right_branch], []) ] )) + +(** Expand "IF{EQ|NEQ|LT|GT|LE|GE}" + into "{EQ|NEQ|LT|GT|LE|GE} ; IF" +*) +let test_if_cmp_macros_expansion () = + assert_if_cmp_macros "IFCMPEQ" "EQ" + >>? fun () -> + assert_if_cmp_macros "IFCMPNEQ" "NEQ" + >>? fun () -> + assert_if_cmp_macros "IFCMPLT" "LT" + >>? fun () -> + assert_if_cmp_macros "IFCMPGT" "GT" + >>? fun () -> + assert_if_cmp_macros "IFCMPLE" "LE" + >>? fun () -> assert_if_cmp_macros "IFCMPGE" "GE" + +(****************************************************************************) +(* Fail *) + +(** Expand "FAIL" + into "UNIT ; FAILWITH" +*) +let test_fail_expansion () = + assert_expands + (Prim (zero_loc, "FAIL", [], [])) + (Seq + ( zero_loc, + [Prim (zero_loc, "UNIT", [], []); Prim (zero_loc, "FAILWITH", [], [])] + )) + +(**********************************************************************) +(* assertion *) + +let seq_unit_failwith = + Seq + ( zero_loc, + [Prim (zero_loc, "UNIT", [], []); Prim (zero_loc, "FAILWITH", [], [])] ) + +(* {} {FAIL} *) +let fail_false = [Seq (zero_loc, []); Seq (zero_loc, [seq_unit_failwith])] + +(* {FAIL} {} *) +let fail_true = [Seq (zero_loc, [seq_unit_failwith]); Seq (zero_loc, [])] + +(** Expand "ASSERT" + into "IF {} {FAIL}" +*) +let test_assert_expansion () = + assert_expands + (Prim (zero_loc, "ASSERT", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF", fail_false, [])])) + +let assert_assert_if_compare prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, compare_name, [], []); + Prim (zero_loc, "IF", fail_false, []) ] )) + +(** Expand "ASSERT_{EQ|NEQ|LT|GT|LE|GE}" + into "{EQ|NEQ|LT|GT|LE|GE} ; IF {} {FAIL}" +*) +let test_assert_if () = + assert_assert_if_compare "ASSERT_EQ" "EQ" + >>? fun () -> + assert_assert_if_compare "ASSERT_NEQ" "NEQ" + >>? fun () -> + assert_assert_if_compare "ASSERT_LT" "LT" + >>? fun () -> + assert_assert_if_compare "ASSERT_LE" "LE" + >>? fun () -> + assert_assert_if_compare "ASSERT_GT" "GT" + >>? fun () -> assert_assert_if_compare "ASSERT_GE" "GE" + +let assert_cmp_if prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [], [])) + (Seq + ( zero_loc, + [ Seq + ( zero_loc, + [ Prim (zero_loc, "COMPARE", [], []); + Prim (zero_loc, compare_name, [], []) ] ); + Prim (zero_loc, "IF", fail_false, []) ] )) + +(** Expand "ASSERT_CMP{EQ|NEQ|LT|GT|LE|GE}" + into "COMPARE ; {EQ|NEQ|LT|GT|LE|GE} ; IF {} {FAIL}" +*) +let test_assert_cmp_if () = + assert_cmp_if "ASSERT_CMPEQ" "EQ" + >>? fun () -> + assert_cmp_if "ASSERT_CMPNEQ" "NEQ" + >>? fun () -> + assert_cmp_if "ASSERT_CMPLT" "LT" + >>? fun () -> + assert_cmp_if "ASSERT_CMPLE" "LE" + >>? fun () -> + assert_cmp_if "ASSERT_CMPGT" "GT" + >>? fun () -> assert_cmp_if "ASSERT_CMPGE" "GE" + +(* The work of merge request !628 + > ASSERT_LEFT @x => IF_LEFT {RENAME @x} {FAIL} + > ASSERT_RIGHT @x => IF_LEFT {FAIL} {RENAME @x} + > ASSERT_SOME @x => IF_NONE {FAIL} {RENAME @x} +*) + +let may_rename annot = Seq (zero_loc, [Prim (zero_loc, "RENAME", [], annot)]) + +let fail_false_may_rename = + [ may_rename ["@annot"]; + Seq + ( zero_loc, + [ Seq + ( zero_loc, + [ Prim (zero_loc, "UNIT", [], []); + Prim (zero_loc, "FAILWITH", [], []) ] ) ] ) ] + +let fail_true_may_rename = + [ Seq + ( zero_loc, + [ Seq + ( zero_loc, + [ Prim (zero_loc, "UNIT", [], []); + Prim (zero_loc, "FAILWITH", [], []) ] ) ] ); + may_rename ["@annot"] ] + +(** Expand "ASSERT_SOME @annot" + into "IF_NONE { } {UNIT;FAILWITH}" + using variable annotation "@annot" +*) +let test_assert_some_annot () = + assert_expands + (Prim (zero_loc, "ASSERT_SOME", [], ["@annot"])) + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_true_may_rename, [])])) + +(** Expand "ASSERT_SOME" + into "IF_NONE { UNIT;FAILWITH } { }" +*) +let test_assert_some () = + assert_expands + (Prim (zero_loc, "ASSERT_SOME", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_true, [])])) + +(** Expand "ASSERT_LEFT @annot" + into "IF_LEFT { } {UNIT;FAILWITH}" + using variable annotation "@annot" +*) +let test_assert_left_annot () = + assert_expands + (Prim (zero_loc, "ASSERT_LEFT", [], ["@annot"])) + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_false_may_rename, [])])) + +(** Expand "ASSERT_LEFT" + into "IF_LEFT { } {UNIT;FAILWITH}" +*) +let test_assert_left () = + assert_expands + (Prim (zero_loc, "ASSERT_LEFT", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_false, [])])) + +(** Expand "ASSERT_RIGHT @annot" + into "IF_LEFT {UNIT;FAILWITH} { }" + using variable annotation "@annot" +*) +let test_assert_right_annot () = + assert_expands + (Prim (zero_loc, "ASSERT_RIGHT", [], ["@annot"])) + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_true_may_rename, [])])) + +(** Expand "ASSERT_RIGHT" + into "IF_LEFT {UNIT;FAILWITH} { }" +*) +let test_assert_right () = + assert_expands + (Prim (zero_loc, "ASSERT_RIGHT", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_true, [])])) + +(** Expand "ASSERT_NONE" + into "IF_NONE { } { UNIT;FAILWITH }" +*) +let test_assert_none () = + assert_expands + (Prim (zero_loc, "ASSERT_NONE", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_false, [])])) + +(***********************************************************************) +(*Syntactic Conveniences*) + +(* diip *) + +(** Expand "DIP" into "DIP". + Expand "DIIIIIIIIP" into "DIP 8". + Expand "DIIP" into "DIP 2". +*) +let test_diip () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_expands + (Prim (zero_loc, "DIP", [code], [])) + (Prim (zero_loc, "DIP", [code], [])) + >>? fun () -> + assert_expands + (Prim (zero_loc, "DIIIIIIIIP", [code], [])) + (Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 8); code], [])) + >>? fun () -> + assert_expands + (Prim (zero_loc, "DIIP", [code], [])) + (Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 2); code], [])) + +(* pair *) + +(** Expand "PAIR" + into "PAIR" +*) +let test_pair () = + assert_expands + (Prim (zero_loc, "PAIR", [], [])) + (Prim (zero_loc, "PAIR", [], [])) + +(** Expand "PAPPAIIR" + into "DIP {PAIR}; DIP {PAIR}; PAIR" +*) +let test_pappaiir () = + let pair = Prim (zero_loc, "PAIR", [], []) in + assert_expands + (Prim (zero_loc, "PAPPAIIR", [], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "DIP", [Seq (zero_loc, [pair])], []); + Prim (zero_loc, "DIP", [Seq (zero_loc, [pair])], []); + pair ] )) + +(* unpair *) + +(** Expand "UNPAIR" + into "DUP ; CAR ; DIP {CDR}" +*) +let test_unpair () = + assert_expands + (Prim (zero_loc, "UNPAIR", [], [])) + (Prim (zero_loc, "UNPAIR", [], [])) + +(* duup *) + +(** Expand "DUUP" + into "DIP {DUP} ; SWAP" +*) +let test_duup () = + assert_expands + (Prim (zero_loc, "DUUP", [], [])) + (Prim (zero_loc, "DUP", [Int (zero_loc, Z.of_int 2)], [])) + +(* car/cdr *) + +(** Expand "CAR" into "CAR" + Expand "CDR" into "CDR" + Expand "CADR" into "CAR ; CDR" + Expand "CDAR" into "CDR ; CAR" +*) +let test_caddadr_expansion () = + let car = Prim (zero_loc, "CAR", [], []) in + assert_expands (Prim (zero_loc, "CAR", [], [])) car + >>? fun () -> + let cdr = Prim (zero_loc, "CDR", [], []) in + assert_expands (Prim (zero_loc, "CDR", [], [])) cdr + >>? fun () -> + assert_expands (Prim (zero_loc, "CADR", [], [])) (Seq (zero_loc, [car; cdr])) + >>? fun () -> + assert_expands (Prim (zero_loc, "CDAR", [], [])) (Seq (zero_loc, [cdr; car])) + +let test_carn_cdrn_expansion () = + let car n = Prim (zero_loc, "CAR", [Int (zero_loc, Z.of_int n)], []) in + let cdr n = Prim (zero_loc, "CDR", [Int (zero_loc, Z.of_int n)], []) in + let get n = + Seq (zero_loc, [Prim (zero_loc, "GET", [Int (zero_loc, Z.of_int n)], [])]) + in + assert_expands (cdr 0) (get 0) + >>? fun () -> + assert_expands (car 0) (get 1) + >>? fun () -> + assert_expands (cdr 1) (get 2) + >>? fun () -> + assert_expands (car 1) (get 3) >>? fun () -> assert_expands (cdr 2) (get 4) + +(* if_some *) + +(** Expand "IF_SOME { 1 } { 2 }" + into "IF_NONE { 2 } { 1 }" +*) +let test_if_some () = + assert_expands + (Prim (zero_loc, "IF_SOME", [right_branch; left_branch], [])) + (Seq + (zero_loc, [Prim (zero_loc, "IF_NONE", [left_branch; right_branch], [])])) + +(*set_caddadr*) + +(** Expand "SET_CAR" + into "CDR; SWAP; PAIR" +*) +let test_set_car_expansion () = + assert_expands + (Prim (zero_loc, "SET_CAR", [], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]) ] )) + +(** Expand "SET_CDR" + into "CAR; PAIR" +*) +let test_set_cdr_expansion () = + assert_expands + (Prim (zero_loc, "SET_CDR", [], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]) ] )) + +(** Expand "SET_CADR" + into "DUP; DIP {CAR; { CAR; PAIR }}; CDR; SWAP; PAIR" +*) +let test_set_cadr_expansion () = + let set_car = + Seq + ( zero_loc, + [ Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]) ] ) + in + assert_expands + (Prim (zero_loc, "SET_CADR", [], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); set_car])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] )) + +(** Expand "SET_CDAR" + into "DUP; DIP {CDR; { CDR; SWAP; PAIR }}; CAR; PAIR" +*) +let test_set_cdar_expansion () = + let set_cdr = + Seq + ( zero_loc, + [ Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]) ] ) + in + assert_expands + (Prim (zero_loc, "SET_CDAR", [], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CDR", [], ["@%%"]); set_cdr])], + [] ); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] )) + +(* TO BE CHANGE IN THE DOCUMENTATION: @MR!791 + FROM: + > MAP_CAR code => DUP ; CDR ; DIP { CAR ; code } ; SWAP ; PAIR + TO: + > MAP_CAR code => DUP ; CDR ; DIP { CAR ; {code} } ; SWAP ; PAIR +*) + +(** Expand "MAP_CAR {CAR}" + into "DUP; CDR; DIP {CAR; CAR}; SWAP; PAIR" +*) +let test_map_car () = + (* code is a sequence *) + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_expands + (Prim (zero_loc, "MAP_CAR", [code], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], []); code])], + [] ); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]) ] )) + +(** Expand "MAP_CDR {CAR}" + into "DUP; CDR; CAR; SWAP; CAR; PAIR" +*) +let test_map_cdr () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_expands + (Prim (zero_loc, "MAP_CDR", [code], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + code; + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]) ] )) + +(** Expand "MAP_CAADR {CAR}" + into "DUP; + DIP { CAR; + DUP; + DIP { CAR; + DUP; + CDR; + CAR; + SWAP; + CAR; + PAIR + } + CDR; + SWAP; + PAIR + }; + CDR; + SWAP; + PAIR" +*) +let test_map_caadr () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + let map_cdr = + Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + code; + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]) ] ) + in + let map_cadr = + Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); map_cdr])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] ) + in + assert_expands + (Prim (zero_loc, "MAP_CAADR", [code], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); map_cadr])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] )) + +(** Expand "MAP_CDADR" + into "DUP; + DIP { CDR; + DUP; + DIP { CAR; + DUP; + CDR; + CAR; + SWAP; + CAR; + PAIR + }; + CDR; + CAR; + PAIR + }; + CAR; + PAIR" +*) +let test_map_cdadr () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + let map_cdr = + Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + code; + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]) ] ) + in + let map_cadr = + Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); map_cdr])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] ) + in + assert_expands + (Prim (zero_loc, "MAP_CDADR", [code], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CDR", [], ["@%%"]); map_cadr])], + [] ); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] )) + +(****************************************************************************) +(* Unexpand tests *) +(****************************************************************************) + +(** Asserts that unexpanding the expression [original] conforms with + the canonical form of [ex]. + [unparse.Michelson_v1_parser.unexpanded] contains the original + expression with macros *) +let assert_unexpansion original ex = + let ({Michelson_v1_parser.expanded; _}, errors) = + let source = print (Micheline.strip_locations original) in + Michelson_v1_parser.expand_all ~source ~original + in + let unparse = Michelson_v1_printer.unparse_expression expanded in + match errors with + | [] -> + Assert.equal + ~print + unparse.Michelson_v1_parser.unexpanded + (Micheline.strip_locations ex) ; + ok () + | _ :: _ -> + Error errors + +let assert_unexpansion_consistent original = + let ({Michelson_v1_parser.expanded; _}, errors) = + let source = print (Micheline.strip_locations original) in + Michelson_v1_parser.expand_all ~source ~original + in + match errors with + | _ :: _ -> + Error errors + | [] -> + let {Michelson_v1_parser.unexpanded; _} = + Michelson_v1_printer.unparse_expression expanded + in + Assert.equal ~print unexpanded (Micheline.strip_locations original) ; + ok () + +(** Unexpanding "UNIT; FAILWITH" + yields "FAIL" +*) +let test_unexpand_fail () = + assert_unexpansion + (Seq + ( zero_loc, + [Prim (zero_loc, "UNIT", [], []); Prim (zero_loc, "FAILWITH", [], [])] + )) + (Prim (zero_loc, "FAIL", [], [])) + +(** Unexpanding "IF_LEFT { 1 } { 2 }" + yields "IF_RIGHT { 2 } { 1 }" +*) +let test_unexpand_if_right () = + assert_unexpansion + (Seq + (zero_loc, [Prim (zero_loc, "IF_LEFT", [left_branch; right_branch], [])])) + (Prim (zero_loc, "IF_RIGHT", [right_branch; left_branch], [])) + +(** IF_NONE + Unexpanding "IF_NONE { 1 } { 2 }" + yields "IF_SOME { 2 } { 1 }" +*) +let test_unexpand_if_some () = + assert_unexpansion + (Seq + (zero_loc, [Prim (zero_loc, "IF_NONE", [left_branch; right_branch], [])])) + (Prim (zero_loc, "IF_SOME", [right_branch; left_branch], [])) + +(** Unexpanding "IF {} { UNIT; FAILWITH }" + yields "ASSERT" +*) +let test_unexpand_assert () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF", fail_false, [])])) + (Prim (zero_loc, "ASSERT", [], [])) + +let assert_unexpansion_assert_if_compare compare_name prim_name = + assert_unexpansion + (Seq + ( zero_loc, + [ Prim (zero_loc, compare_name, [], []); + Prim (zero_loc, "IF", fail_false, []) ] )) + (Prim (zero_loc, prim_name, [], [])) + +(** Unexpanding "{EQ|NEQ|LT|LE|GT|GE} ; IF {} {FAIL}" + yields "ASSERT_{EQ|NEQ|LT|LE|GT|GE}" +*) +let test_unexpand_assert_if () = + assert_unexpansion_assert_if_compare "EQ" "ASSERT_EQ" + >>? fun () -> + assert_unexpansion_assert_if_compare "NEQ" "ASSERT_NEQ" + >>? fun () -> + assert_unexpansion_assert_if_compare "LT" "ASSERT_LT" + >>? fun () -> + assert_unexpansion_assert_if_compare "LE" "ASSERT_LE" + >>? fun () -> + assert_unexpansion_assert_if_compare "GT" "ASSERT_GT" + >>? fun () -> assert_unexpansion_assert_if_compare "GE" "ASSERT_GE" + +let assert_unexpansion_assert_cmp_if_compare compare_name prim_name = + assert_unexpansion + (Seq + ( zero_loc, + [ Seq + ( zero_loc, + [ Prim (zero_loc, "COMPARE", [], []); + Prim (zero_loc, compare_name, [], []) ] ); + Prim (zero_loc, "IF", fail_false, []) ] )) + (Prim (zero_loc, prim_name, [], [])) + +(** Unexpanding "COMPARE; {EQ|NEQ|LT|LE|GT|GE}; IF {} {FAIL}" + yields "ASSERT_CMP{EQ|NEQ|LT|LE|GT|GE}" +*) +let test_unexpansion_assert_cmp_if () = + assert_unexpansion_assert_cmp_if_compare "EQ" "ASSERT_CMPEQ" + >>? fun () -> + assert_unexpansion_assert_cmp_if_compare "NEQ" "ASSERT_CMPNEQ" + >>? fun () -> + assert_unexpansion_assert_cmp_if_compare "LT" "ASSERT_CMPLT" + >>? fun () -> + assert_unexpansion_assert_cmp_if_compare "LE" "ASSERT_CMPLE" + >>? fun () -> + assert_unexpansion_assert_cmp_if_compare "GT" "ASSERT_CMPGT" + >>? fun () -> assert_unexpansion_assert_cmp_if_compare "GE" "ASSERT_CMPGE" + +(** Unexpanding "IF_NONE { FAIL } { RENAME @annot }" + yields "ASSERT_SOME @annot" +*) +let test_unexpand_assert_some_annot () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_true_may_rename, [])])) + (Prim (zero_loc, "ASSERT_SOME", [], ["@annot"])) + +(** Unexpanding "IF_LEFT { RENAME @annot } { FAIL }" + yields "ASSERT_LEFT @annot" +*) +let test_unexpand_assert_left_annot () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_false_may_rename, [])])) + (Prim (zero_loc, "ASSERT_LEFT", [], ["@annot"])) + +(** Unexpanding "IF_LEFT { FAIL } { RENAME @annot }" + yields "ASSERT_RIGHT @annot" +*) +let test_unexpand_assert_right_annot () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_true_may_rename, [])])) + (Prim (zero_loc, "ASSERT_RIGHT", [], ["@annot"])) + +(** Unexpanding "IF_NONE {} { FAIL }" + yields "ASSERT_NONE" +*) +let test_unexpand_assert_none () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_false, [])])) + (Prim (zero_loc, "ASSERT_NONE", [], [])) + +(** Unexpanding "IF_NONE { FAIL } {}" + yields "ASSERT_SOME" +*) +let test_unexpand_assert_some () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_true, [])])) + (Prim (zero_loc, "ASSERT_SOME", [], [])) + +(** Unexpanding "IF_LEFT {} { FAIL }" + yields "ASSERT_LEFT" +*) +let test_unexpand_assert_left () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_false, [])])) + (Prim (zero_loc, "ASSERT_LEFT", [], [])) + +(** Unexpanding "IF_LEFT { FAIL } {}" + yields "ASSERT_RIGHT" +*) +let test_unexpand_assert_right () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_true, [])])) + (Prim (zero_loc, "ASSERT_RIGHT", [], [])) + +(** Unexpanding "DUP; CAR; DIP { CDR }" + yields "UNPAIR" +*) +let test_unexpand_unpair () = + assert_unexpansion + (Prim (zero_loc, "UNPAIR", [], [])) + (Prim (zero_loc, "UNPAIR", [], [])) + +(** Unexpanding "PAIR" + yields "PAIR" +*) +let test_unexpand_pair () = + assert_unexpansion + (Prim (zero_loc, "PAIR", [], [])) + (Prim (zero_loc, "PAIR", [], [])) + +(** Unexpanding "DIP { PAIR }; DIP { PAIR }; PAIR" + yields "PAPPAIIR" +*) +let test_unexpand_pappaiir () = + assert_unexpansion + (Seq + ( zero_loc, + [ Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "PAIR", [], [])])], + [] ); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "PAIR", [], [])])], + [] ); + Prim (zero_loc, "PAIR", [], []) ] )) + (Prim (zero_loc, "PAPPAIIR", [], [])) + +(** Unexpanding "DIP { DUP }; SWAP" + yields "DUP 2" +*) +let test_unexpand_duup () = + assert_unexpansion + (Seq + ( zero_loc, + [ Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "DUP", [], [])])], + [] ); + Prim (zero_loc, "SWAP", [], []) ] )) + (Prim (zero_loc, "DUP", [Int (zero_loc, Z.of_int 2)], [])) + +(** Unexpanding "CAR" yields "CAR" + Unexpanding "CDR" yields "CDR" + Unexpanding "CAR; CDR" yields "CADR" + Unexpanding "CDR; CAR" yields "CDAR" +*) +let test_unexpand_caddadr () = + let car = Prim (zero_loc, "CAR", [], []) in + let cdr = Prim (zero_loc, "CDR", [], []) in + assert_unexpansion (Seq (zero_loc, [car])) car + >>? fun () -> + assert_unexpansion (Seq (zero_loc, [cdr])) cdr + >>? fun () -> + assert_unexpansion + (Seq (zero_loc, [car; cdr])) + (Prim (zero_loc, "CADR", [], [])) + >>? fun () -> + assert_unexpansion + (Seq (zero_loc, [cdr; car])) + (Prim (zero_loc, "CDAR", [], [])) + +let test_unexpand_carn_cdrn () = + let car n = Prim (zero_loc, "CAR", [Int (zero_loc, Z.of_int n)], []) in + let cdr n = Prim (zero_loc, "CDR", [Int (zero_loc, Z.of_int n)], []) in + let get n = + Seq (zero_loc, [Prim (zero_loc, "GET", [Int (zero_loc, Z.of_int n)], [])]) + in + assert_unexpansion (get 0) (cdr 0) + >>? fun () -> + assert_unexpansion (get 1) (car 0) + >>? fun () -> + assert_unexpansion (get 2) (cdr 1) + >>? fun () -> + assert_unexpansion (get 3) (car 1) + >>? fun () -> assert_unexpansion (get 4) (cdr 2) + +(** Unexpanding "CDR; SWAP; PAIR" + yields "SET_CAR" +*) +let test_unexpand_set_car () = + assert_unexpansion + (Seq + ( zero_loc, + [ Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]) ] )) + (Prim (zero_loc, "SET_CAR", [], [])) + +(** Unexpanding "CAR; PAIR" + yields "SET_CDR" +*) +let test_unexpand_set_cdr () = + assert_unexpansion + (Seq + ( zero_loc, + [ Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]) ] )) + (Prim (zero_loc, "SET_CDR", [], [])) + +(** Unexpanding "DUP; CAR; DROP; CDR; SWAP; PAIR" + yields "SET_CAR" +*) +let test_unexpand_set_car_annot () = + assert_unexpansion + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CAR", [], ["%@"]); + Prim (zero_loc, "DROP", [], []); + Prim (zero_loc, "CDR", [], []); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], []) ] )) + (Prim (zero_loc, "SET_CAR", [], ["%@"])) + +(** Unexpanding "DUP; CDR; DROP; CAR; PAIR" + yields "SET_CDR" +*) +let test_unexpand_set_cdr_annot () = + assert_unexpansion + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], ["%@"]); + Prim (zero_loc, "DROP", [], []); + Prim (zero_loc, "CAR", [], []); + Prim (zero_loc, "PAIR", [], []) ] )) + (Prim (zero_loc, "SET_CDR", [], ["%@"])) + +(** Unexpanding "DUP; DIP { CAR; CAR; PAIR }; CDR; SWAP; PAIR" + yields "SET_CADR" +*) +let test_unexpand_set_cadr () = + let set_car = + Seq + ( zero_loc, + [ Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]) ] ) + in + assert_unexpansion + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); set_car])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] )) + (Prim (zero_loc, "SET_CADR", [], [])) + +let test_unexpand_set_cdar () = + let set_cdr = + Seq + ( zero_loc, + [ Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]) ] ) + in + assert_unexpansion + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CDR", [], ["@%%"]); set_cdr])], + [] ); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] )) + (Prim (zero_loc, "SET_CDAR", [], [])) + +(* FIXME: Seq()(Prim): does not parse, raise an error unparse *) +let test_unexpand_map_car () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_unexpansion + (Prim (zero_loc, "MAP_CAR", [code], [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim + ( zero_loc, + "DIP", + [ Seq + ( zero_loc, + [ Prim (zero_loc, "CAR", [], []); + Prim (zero_loc, "CAR", [], []) ] ) ], + [] ); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]) ] )) + +(***********************************************************************) +(*BUG: the test with MAP_CDR or any map with "D" inside fail *) + +let _test_unexpand_map_cdr () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_unexpansion + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + code; + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], []); + Prim (zero_loc, "PAIR", [], []) ] )) + (Prim (zero_loc, "MAP_CDR", [code], [])) + +let _test_unexpand_map_caadr () = + let code = [Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])])] in + let map_cdr = + Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [ Seq + ( zero_loc, + [ Prim (zero_loc, "CAR", [], ["@%%"]); + Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]) ] ) ] ) ], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] ) + in + assert_unexpansion + (Prim (zero_loc, "MAP_CAAR", code, [])) + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); map_cdr])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] )) + +let _test_unexpand_map_cdadr () = + let code = [Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])])] in + let map_cdr = + Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [ Seq + ( zero_loc, + [ Prim (zero_loc, "CAR", [], ["@%%"]); + Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]) ] ) ] ) ], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] ) + in + assert_unexpansion + (Seq + ( zero_loc, + [ Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CDR", [], ["@%%"]); map_cdr])], + [] ); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]) ] )) + (Prim (zero_loc, "MAP_CDADR", code, [])) + +let test_unexpand_diip () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_unexpansion + (Prim (zero_loc, "DIIP", [code], [])) + (Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 2); code], [])) + +(** Unexpanding "DIP { DIP { DIP { DUP }; SWAP" + yields "DIIP { DIP { DUP }; SWAP }" +*) +let test_unexpand_diip_duup1 () = + let single code = Seq (zero_loc, [code]) in + let cst str = Prim (zero_loc, str, [], []) in + let app str code = Prim (zero_loc, str, [code], []) in + let dip = app "DIP" in + let diip code = + Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 2); code], []) + in + let dup = cst "DUP" in + let swap = cst "SWAP" in + let dip_dup_swap = Seq (zero_loc, [dip (single dup); swap]) in + assert_unexpansion + (* { DIP { DIP { DIP { DUP }; SWAP }}} *) + (single (dip (single (dip dip_dup_swap)))) + (* DIIP { DIP { DUP }; SWAP } *) + (diip dip_dup_swap) + +(** Unexpanding "DIP { DIP {{ DIP { DUP }; SWAP" + yields "DIIP { DUUP }" +*) +let test_unexpand_diip_duup2 () = + let single code = Seq (zero_loc, [code]) in + let cst str = Prim (zero_loc, str, [], []) in + let app str code = Prim (zero_loc, str, [code], []) in + let dip = app "DIP" in + let diip code = + Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 2); code], []) + in + let dup = cst "DUP" in + let duup = Prim (zero_loc, "DUP", [Int (zero_loc, Z.of_int 2)], []) in + let swap = cst "SWAP" in + let dip_dup_swap = Seq (zero_loc, [dip (single dup); swap]) in + assert_unexpansion + (* { DIP { DIP {{ DIP { DUP }; SWAP }}}} *) + (single (dip (single (dip (single dip_dup_swap))))) + (* DIIP { DUUP } *) + (diip (single duup)) + +(*****************************************************************************) +(* Test *) +(*****************************************************************************) + +let tests = + [ (*compare*) + ("compare expansion", fun _ -> Lwt.return (test_compare_marco_expansion ())); + ( "if compare expansion", + fun _ -> Lwt.return (test_if_compare_macros_expansion ()) ); + ( "if compare expansion: IFCMP", + fun _ -> Lwt.return (test_if_cmp_macros_expansion ()) ); + (*fail*) + ("fail expansion", fun _ -> Lwt.return (test_fail_expansion ())); + (*assertion*) + ("assert expansion", fun _ -> Lwt.return (test_assert_expansion ())); + ("assert if expansion", fun _ -> Lwt.return (test_assert_if ())); + ("assert cmpif expansion", fun _ -> Lwt.return (test_assert_cmp_if ())); + ("assert none expansion", fun _ -> Lwt.return (test_assert_none ())); + ("assert some expansion", fun _ -> Lwt.return (test_assert_some ())); + ("assert left expansion", fun _ -> Lwt.return (test_assert_left ())); + ("assert right expansion", fun _ -> Lwt.return (test_assert_right ())); + ( "assert some annot expansion", + fun _ -> Lwt.return (test_assert_some_annot ()) ); + ( "assert left annot expansion", + fun _ -> Lwt.return (test_assert_left_annot ()) ); + ( "assert right annot expansion", + fun _ -> Lwt.return (test_assert_right_annot ()) ); + (*syntactic conveniences*) + ("diip expansion", fun _ -> Lwt.return (test_diip ())); + ("duup expansion", fun _ -> Lwt.return (test_duup ())); + ("pair expansion", fun _ -> Lwt.return (test_pair ())); + ("pappaiir expansion", fun _ -> Lwt.return (test_pappaiir ())); + ("unpair expansion", fun _ -> Lwt.return (test_unpair ())); + ("caddadr expansion", fun _ -> Lwt.return (test_caddadr_expansion ())); + ( "carn and cdrn expansion", + fun _ -> Lwt.return (test_carn_cdrn_expansion ()) ); + ("if_some expansion", fun _ -> Lwt.return (test_if_some ())); + ("set_car expansion", fun _ -> Lwt.return (test_set_car_expansion ())); + ("set_cdr expansion", fun _ -> Lwt.return (test_set_cdr_expansion ())); + ("set_cadr expansion", fun _ -> Lwt.return (test_set_cadr_expansion ())); + ("set_cdar expansion", fun _ -> Lwt.return (test_set_cdar_expansion ())); + ("map_car expansion", fun _ -> Lwt.return (test_map_car ())); + ("map_cdr expansion", fun _ -> Lwt.return (test_map_cdr ())); + ("map_caadr expansion", fun _ -> Lwt.return (test_map_caadr ())); + ("map_cdadr expansion", fun _ -> Lwt.return (test_map_cdadr ())); + (*Unexpand*) + ("fail unexpansion", fun _ -> Lwt.return (test_unexpand_fail ())); + ("if_right unexpansion", fun _ -> Lwt.return (test_unexpand_if_right ())); + ("if_some unexpansion", fun _ -> Lwt.return (test_unexpand_if_some ())); + ("assert unexpansion", fun _ -> Lwt.return (test_unexpand_assert ())); + ("assert_if unexpansion", fun _ -> Lwt.return (test_unexpand_assert_if ())); + ( "assert_cmp_if unexpansion", + fun _ -> Lwt.return (test_unexpansion_assert_cmp_if ()) ); + ( "assert_none unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_none ()) ); + ( "assert_some unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_some ()) ); + ( "assert_left unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_left ()) ); + ( "assert_right unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_right ()) ); + ( "assert_some annot unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_some_annot ()) ); + ( "assert_left annot unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_left_annot ()) ); + ( "assert_right annot unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_right_annot ()) ); + ("unpair unexpansion", fun _ -> Lwt.return (test_unexpand_unpair ())); + ("pair unexpansion", fun _ -> Lwt.return (test_unexpand_pair ())); + ("pappaiir unexpansion", fun _ -> Lwt.return (test_unexpand_pappaiir ())); + ("duup unexpansion", fun _ -> Lwt.return (test_unexpand_duup ())); + ("caddadr unexpansion", fun _ -> Lwt.return (test_unexpand_caddadr ())); + ( "carn and cdrn unexpansion", + fun _ -> Lwt.return (test_unexpand_carn_cdrn ()) ); + ("set_car unexpansion", fun _ -> Lwt.return (test_unexpand_set_car ())); + ("set_cdr unexpansion", fun _ -> Lwt.return (test_unexpand_set_cdr ())); + ("set_cdar unexpansion", fun _ -> Lwt.return (test_unexpand_set_cdar ())); + ("set_cadr unexpansion", fun _ -> Lwt.return (test_unexpand_set_cadr ())); + ( "set_car annot unexpansion", + fun _ -> Lwt.return (test_unexpand_set_car_annot ()) ); + ( "set_cdr annot unexpansion", + fun _ -> Lwt.return (test_unexpand_set_cdr_annot ()) ); + ("map_car unexpansion", fun _ -> Lwt.return (test_unexpand_map_car ())); + ("diip unexpansion", fun _ -> Lwt.return (test_unexpand_diip ())); + ( "diip_duup1 unexpansion", + fun _ -> Lwt.return (test_unexpand_diip_duup1 ()) ); + ( "diip_duup2 unexpansion", + fun _ -> Lwt.return (test_unexpand_diip_duup2 ()) ) + (***********************************************************************) + (*BUG + the function in Michelson_v1_macros.unexpand_map_caddadr + failed to test the case with the character "D". + It returns an empty {} for the expand *) + (*"diip unexpansion", (fun _ -> Lwt.return (test_unexpand_diip ())) ;*) + (*"map_cdr unexpansion", (fun _ -> Lwt.return (test_unexpand_map_cdr ())) ;*) + (*"map_caadr unexpansion", (fun _ -> Lwt.return (test_unexpand_map_caadr ())) ;*) + (*"map_cdadr unexpansion", (fun _ -> Lwt.return (test_unexpand_map_cdadr ())) ;*) + ] + +let wrap (n, f) = + Alcotest_lwt.test_case n `Quick (fun _ () -> + f () + >>= function + | Ok () -> + Lwt.return_unit + | Error error -> + Format.kasprintf Stdlib.failwith "%a" pp_print_error error) + +let () = + Alcotest_lwt.run + ~argv:[|""|] + "tezos-lib-client" + [("micheline v1 macros", List.map wrap tests)] + |> Lwt_main.run diff --git a/src/proto_009_PsFLoren/lib_client/tezos-client-009-PsFLoren.opam b/src/proto_009_PsFLoren/lib_client/tezos-client-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..dc2506984f07df08f303a0d7653c8870038942bd --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client/tezos-client-009-PsFLoren.opam @@ -0,0 +1,27 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-protocol-environment" + "tezos-protocol-009-PsFLoren" + "tezos-shell-services" + "tezos-client-base-unix" + "tezos-mockup-registration" + "tezos-proxy" + "tezos-signer-backends" + "tezos-protocol-009-PsFLoren-parameters" + "tezos-protocol-plugin-009-PsFLoren" + "alcotest-lwt" { with-test & >= "1.1.0" } +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol specific library for `tezos-client`" diff --git a/src/proto_009_PsFLoren/lib_client_commands/.ocamlformat b/src/proto_009_PsFLoren/lib_client_commands/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_client_commands/alpha_commands_registration.ml b/src/proto_009_PsFLoren/lib_client_commands/alpha_commands_registration.ml new file mode 100644 index 0000000000000000000000000000000000000000..4280e5a40fd925bd7ad74bbccfee4eecc843c615 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/alpha_commands_registration.ml @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = + Client_commands.register Protocol.hash + @@ fun network -> + List.map (Clic.map_command (new Protocol_client_context.wrap_full)) + @@ Client_proto_programs_commands.commands () + @ Client_proto_contracts_commands.commands () + @ Client_proto_context_commands.commands network () + @ Client_proto_multisig_commands.commands () + @ Client_proto_mockup_commands.commands () + @ Client_sapling_commands.commands () + @ Client_proto_utils_commands.commands () diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_context_commands.ml b/src/proto_009_PsFLoren/lib_client_commands/client_proto_context_commands.ml new file mode 100644 index 0000000000000000000000000000000000000000..f4bd4f2d37052b7ed6435f4ee33363c5c1fac336 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_context_commands.ml @@ -0,0 +1,1649 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline +open Client_proto_context +open Client_proto_contracts +open Client_proto_programs +open Client_keys +open Client_proto_args + +let encrypted_switch = + Clic.switch ~long:"encrypted" ~doc:"encrypt the key on-disk" () + +let dry_run_switch = + Clic.switch + ~long:"dry-run" + ~short:'D' + ~doc:"don't inject the operation, just display it" + () + +let verbose_signing_switch = + Clic.switch + ~long:"verbose-signing" + ~doc:"display extra information before signing the operation" + () + +let report_michelson_errors ?(no_print_source = false) ~msg + (cctxt : #Client_context.printer) = function + | Error errs -> + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:(not no_print_source) + ~show_source:(not no_print_source) + ?parsed:None) + errs + >>= fun () -> cctxt#error "%s" msg >>= fun () -> Lwt.return_none + | Ok data -> + Lwt.return_some data + +let json_file_or_text_parameter = + Clic.parameter (fun _ p -> + match String.split ~limit:1 ':' p with + | ["text"; text] -> + return (Ezjsonm.from_string text) + | ["file"; path] -> + Lwt_utils_unix.Json.read_file path + | _ -> ( + if Sys.file_exists p then Lwt_utils_unix.Json.read_file p + else + try return (Ezjsonm.from_string p) + with Ezjsonm.Parse_error _ -> + failwith "Neither an existing file nor valid JSON: '%s'" p )) + +let data_parameter = + Clic.parameter (fun _ data -> + Lwt.return + ( Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression data )) + +let non_negative_param = + Clic.parameter (fun _ s -> + match int_of_string_opt s with + | Some i when i >= 0 -> + return i + | _ -> + failwith "Parameter should be a non-negative integer literal") + +let block_hash_param = + Clic.parameter (fun _ s -> + try return (Block_hash.of_b58check_exn s) + with _ -> failwith "Parameter '%s' is an invalid block hash" s) + +let group = + { + Clic.name = "context"; + title = "Block contextual commands (see option -block)"; + } + +let alphanet = {Clic.name = "alphanet"; title = "Alphanet only commands"} + +let binary_description = + {Clic.name = "description"; title = "Binary Description"} + +let transfer_command amount source destination cctxt + ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + arg, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap, + entrypoint ) = + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + ( match Contract.is_implicit source with + | None -> + let contract = source in + Managed_contract.get_contract_manager cctxt source + >>=? fun source -> + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + Managed_contract.transfer + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ?fee + ~contract + ~source + ~src_pk + ~src_sk + ~destination + ?entrypoint + ?arg + ~amount + ?gas_limit + ?storage_limit + ?counter + () + | Some source -> + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + transfer + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~destination + ?entrypoint + ?arg + ~amount + ?gas_limit + ?storage_limit + ?counter + () ) + >>= report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + >>= function None -> return_unit | Some (_res, _contracts) -> return_unit + +let tez_of_string_exn index field s = + match Tez.of_string s with + | Some t -> + return t + | None -> + failwith + "Invalid \xEA\x9C\xA9 notation at entry %i, field \"%s\": %s" + index + field + s + +let tez_of_opt_string_exn index field s = + match s with + | None -> + return None + | Some s -> + tez_of_string_exn index field s >>=? fun s -> return (Some s) + +let prepare_batch_operation cctxt ?arg ?fee ?gas_limit ?storage_limit + ?entrypoint source index batch = + Client_proto_contracts.ContractAlias.find_destination cctxt batch.destination + >>=? fun (_, destination) -> + tez_of_string_exn index "amount" batch.amount + >>=? fun amount -> + tez_of_opt_string_exn index "fee" batch.fee + >>=? fun batch_fee -> + let fee = Option.either batch_fee fee in + let arg = Option.either batch.arg arg in + let gas_limit = Option.either batch.gas_limit gas_limit in + let storage_limit = Option.either batch.storage_limit storage_limit in + let entrypoint = Option.either batch.entrypoint entrypoint in + parse_arg_transfer arg + >>=? fun parameters -> + ( match Contract.is_implicit source with + | None -> + Managed_contract.build_transaction_operation + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract:source + ~destination + ?entrypoint + ?arg + ~amount + ?fee + ?gas_limit + ?storage_limit + () + | Some _ -> + return + (build_transaction_operation + ~amount + ~parameters + ?entrypoint + ?fee + ?gas_limit + ?storage_limit + destination) ) + >>=? fun operation -> + return (Injection.Annotated_manager_operation operation) + +let commands network () = + let open Clic in + [ command + ~group + ~desc:"Access the timestamp of the block." + (args1 + (switch ~doc:"output time in seconds" ~short:'s' ~long:"seconds" ())) + (fixed ["get"; "timestamp"]) + (fun seconds (cctxt : Protocol_client_context.full) -> + Shell_services.Blocks.Header.shell_header + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + () + >>=? fun {timestamp = v; _} -> + ( if seconds then cctxt#message "%Ld" (Time.Protocol.to_seconds v) + else cctxt#message "%s" (Time.Protocol.to_notation v) ) + >>= fun () -> return_unit); + command + ~group + ~desc:"Lists all non empty contracts of the block." + no_options + (fixed ["list"; "contracts"]) + (fun () (cctxt : Protocol_client_context.full) -> + list_contract_labels cctxt ~chain:cctxt#chain ~block:cctxt#block + >>=? fun contracts -> + List.iter_s + (fun (alias, hash, kind) -> cctxt#message "%s%s%s" hash kind alias) + contracts + >>= fun () -> return_unit); + command + ~group + ~desc:"Get the balance of a contract." + no_options + ( prefixes ["get"; "balance"; "for"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ stop ) + (fun () (_, contract) (cctxt : Protocol_client_context.full) -> + get_balance cctxt ~chain:cctxt#chain ~block:cctxt#block contract + >>=? fun amount -> + cctxt#answer "%a %s" Tez.pp amount Client_proto_args.tez_sym + >>= fun () -> return_unit); + command + ~group + ~desc:"Get the storage of a contract." + no_options + ( prefixes ["get"; "contract"; "storage"; "for"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ stop ) + (fun () (_, contract) (cctxt : Protocol_client_context.full) -> + get_storage cctxt ~chain:cctxt#chain ~block:cctxt#block contract + >>=? function + | None -> + cctxt#error "This is not a smart contract." + | Some storage -> + cctxt#answer "%a" Michelson_v1_printer.print_expr_unwrapped storage + >>= fun () -> return_unit); + command + ~group + ~desc: + "Get the value associated to a key in the big map storage of a \ + contract (deprecated)." + no_options + ( prefixes ["get"; "big"; "map"; "value"; "for"] + @@ Clic.param ~name:"key" ~desc:"the key to look for" data_parameter + @@ prefixes ["of"; "type"] + @@ Clic.param ~name:"type" ~desc:"type of the key" data_parameter + @@ prefix "in" + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ stop ) + (fun () key key_type (_, contract) (cctxt : Protocol_client_context.full) -> + get_contract_big_map_value + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + (key.expanded, key_type.expanded) + >>=? function + | None -> + cctxt#error "No value associated to this key." + | Some value -> + cctxt#answer "%a" Michelson_v1_printer.print_expr_unwrapped value + >>= fun () -> return_unit); + command + ~group + ~desc:"Get a value in a big map." + no_options + ( prefixes ["get"; "element"] + @@ Clic.param + ~name:"key" + ~desc:"the key to look for" + (Clic.parameter (fun _ s -> + return (Script_expr_hash.of_b58check_exn s))) + @@ prefixes ["of"; "big"; "map"] + @@ Clic.param + ~name:"big_map" + ~desc:"identifier of the big_map" + int_parameter + @@ stop ) + (fun () key id (cctxt : Protocol_client_context.full) -> + get_big_map_value + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + (Big_map.Id.parse_z (Z.of_int id)) + key + >>=? fun value -> + cctxt#answer "%a" Michelson_v1_printer.print_expr_unwrapped value + >>= fun () -> return_unit); + command + ~group + ~desc:"Get the code of a contract." + no_options + ( prefixes ["get"; "contract"; "code"; "for"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ stop ) + (fun () (_, contract) (cctxt : Protocol_client_context.full) -> + get_script cctxt ~chain:cctxt#chain ~block:cctxt#block contract + >>=? function + | None -> + cctxt#error "This is not a smart contract." + | Some {code; storage = _} -> ( + match Script_repr.force_decode code with + | Error errs -> + cctxt#error "%a" Environment.Error_monad.pp_trace errs + | Ok (code, _) -> + let {Michelson_v1_parser.source; _} = + Michelson_v1_printer.unparse_toplevel code + in + cctxt#answer "%a" Format.pp_print_text source >>= return )); + command + ~group + ~desc:"Get the type of an entrypoint of a contract." + no_options + ( prefixes ["get"; "contract"; "entrypoint"; "type"; "of"] + @@ Clic.string ~name:"entrypoint" ~desc:"the entrypoint to describe" + @@ prefixes ["for"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ stop ) + (fun () entrypoint (_, contract) (cctxt : Protocol_client_context.full) -> + Michelson_v1_entrypoints.contract_entrypoint_type + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~entrypoint + >>= Michelson_v1_entrypoints.print_entrypoint_type + cctxt + ~emacs:false + ~contract + ~entrypoint); + command + ~group + ~desc:"Get the entrypoint list of a contract." + no_options + ( prefixes ["get"; "contract"; "entrypoints"; "for"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ stop ) + (fun () (_, contract) (cctxt : Protocol_client_context.full) -> + Michelson_v1_entrypoints.list_contract_entrypoints + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + >>= Michelson_v1_entrypoints.print_entrypoints_list + cctxt + ~emacs:false + ~contract); + command + ~group + ~desc:"Get the list of unreachable paths in a contract's parameter type." + no_options + ( prefixes ["get"; "contract"; "unreachable"; "paths"; "for"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ stop ) + (fun () (_, contract) (cctxt : Protocol_client_context.full) -> + Michelson_v1_entrypoints.list_contract_unreachables + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + >>= Michelson_v1_entrypoints.print_unreachables + cctxt + ~emacs:false + ~contract); + command + ~group + ~desc:"Get the delegate of a contract." + no_options + ( prefixes ["get"; "delegate"; "for"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ stop ) + (fun () (_, contract) (cctxt : Protocol_client_context.full) -> + Client_proto_contracts.get_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + >>=? function + | None -> + cctxt#message "none" >>= fun () -> return_unit + | Some delegate -> + Public_key_hash.rev_find cctxt delegate + >>=? fun mn -> + Public_key_hash.to_source delegate + >>=? fun m -> + cctxt#message + "%s (%s)" + m + (match mn with None -> "unknown" | Some n -> "known as " ^ n) + >>= fun () -> return_unit); + command + ~group + ~desc:"Set the delegate of a contract." + (args9 + fee_arg + dry_run_switch + verbose_signing_switch + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg) + ( prefixes ["set"; "delegate"; "for"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ prefix "to" + @@ Public_key_hash.source_param + ~name:"dlgt" + ~desc:"new delegate of the contract" + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + (_, contract) + delegate + (cctxt : Protocol_client_context.full) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + match Contract.is_implicit contract with + | None -> + Managed_contract.get_contract_manager cctxt contract + >>=? fun source -> + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + Managed_contract.set_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ?fee + ~source + ~src_pk + ~src_sk + contract + (Some delegate) + >>= fun errors -> + report_michelson_errors + ~no_print_source:true + ~msg:"Setting delegate through entrypoints failed." + cctxt + errors + >>= fun _ -> return_unit + | Some mgr -> + Client_keys.get_key cctxt mgr + >>=? fun (_, src_pk, manager_sk) -> + set_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ?fee + mgr + (Some delegate) + ~src_pk + ~manager_sk + >>=? fun _ -> return_unit); + command + ~group + ~desc:"Withdraw the delegate from a contract." + (args9 + fee_arg + dry_run_switch + verbose_signing_switch + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg) + ( prefixes ["withdraw"; "delegate"; "from"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"source contract" + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + (_, contract) + (cctxt : Protocol_client_context.full) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + match Contract.is_implicit contract with + | None -> + Managed_contract.get_contract_manager cctxt contract + >>=? fun source -> + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + Managed_contract.set_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ?fee + ~source + ~src_pk + ~src_sk + contract + None + >>= fun errors -> + report_michelson_errors + ~no_print_source:true + ~msg:"Withdrawing delegate through entrypoints failed." + cctxt + errors + >>= fun _ -> return_unit + | Some mgr -> + Client_keys.get_key cctxt mgr + >>=? fun (_, src_pk, manager_sk) -> + set_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + mgr + None + ?fee + ~src_pk + ~manager_sk + >>= fun _ -> return_unit); + command + ~group + ~desc:"Launch a smart contract on the blockchain." + (args15 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + delegate_arg + (Client_keys.force_switch ()) + init_arg + no_print_source_flag + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg) + ( prefixes ["originate"; "contract"] + @@ RawContractAlias.fresh_alias_param + ~name:"new" + ~desc:"name of the new contract" + @@ prefix "transferring" + @@ tez_param ~name:"qty" ~desc:"amount taken from source" + @@ prefix "from" + @@ ContractAlias.destination_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefix "running" + @@ Program.source_param + ~name:"prg" + ~desc: + "script of the account\n\ + Combine with -init if the storage type is not unit." + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + delegate, + force, + initial_storage, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + alias_name + balance + (_, source) + program + (cctxt : Protocol_client_context.full) -> + RawContractAlias.of_fresh cctxt force alias_name + >>=? fun alias_name -> + Lwt.return (Micheline_parser.no_parsing_error program) + >>=? fun {expanded = code; _} -> + match Contract.is_implicit source with + | None -> + failwith + "only implicit accounts can be the source of an origination" + | Some source -> ( + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + originate_contract + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ?fee + ?gas_limit + ?storage_limit + ~delegate + ~initial_storage + ~balance + ~source + ~src_pk + ~src_sk + ~code + ~fee_parameter + () + >>= fun errors -> + report_michelson_errors + ~no_print_source + ~msg:"origination simulation failed" + cctxt + errors + >>= function + | None -> + return_unit + | Some (_res, contract) -> + if dry_run then return_unit + else + save_contract ~force cctxt alias_name contract + >>=? fun () -> return_unit )); + command + ~group + ~desc: + "Execute multiple transfers from a single source account.\n\ + If one of the transfers fails, none of them get executed." + (args15 + default_fee_arg + dry_run_switch + verbose_signing_switch + default_gas_limit_arg + default_storage_limit_arg + counter_arg + default_arg_arg + no_print_source_flag + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg + default_entrypoint_arg) + ( prefixes ["multiple"; "transfers"; "from"] + @@ ContractAlias.destination_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefix "using" + @@ param + ~name:"transfers.json" + ~desc: + "List of operations originating from the source contract in JSON \ + format (from a file or directly inlined). The input JSON must \ + be an array of objects of the form: '[ {\"destination\": dst, \ + \"amount\": qty (, : ...) } (, ...) ]', where an \ + optional can either be \"fee\", \"gas-limit\", \ + \"storage-limit\", \"arg\", or \"entrypoint\"." + json_file_or_text_parameter + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + arg, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap, + entrypoint ) + (_, source) + operations_json + cctxt -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + let prepare i = + prepare_batch_operation + cctxt + ?arg + ?fee + ?gas_limit + ?storage_limit + ?entrypoint + source + i + in + match + Data_encoding.Json.destruct + (Data_encoding.list + Client_proto_context.batch_transfer_operation_encoding) + operations_json + with + | [] -> + failwith "Empty operation list" + | operations -> + ( match Contract.is_implicit source with + | None -> + Managed_contract.get_contract_manager cctxt source + >>=? fun source -> + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> return (source, src_pk, src_sk) + | Some source -> + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> return (source, src_pk, src_sk) + ) + >>=? fun (source, src_pk, src_sk) -> + List.mapi_ep prepare operations + >>=? fun contents -> + let (Manager_list contents) = Injection.manager_of_list contents in + Injection.inject_manager_operation + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~source + ?fee + ?gas_limit + ?storage_limit + ?counter + ~src_pk + ~src_sk + ~fee_parameter + contents + >>= report_michelson_errors + ~no_print_source + ~msg:"multiple transfers simulation failed" + cctxt + >>= fun _ -> return_unit + | exception (Data_encoding.Json.Cannot_destruct (path, exn2) as exn) + -> ( + match (path, operations_json) with + | ([`Index n], `A lj) -> ( + match List.nth_opt lj n with + | Some j -> + failwith + "Invalid transfer at index %i: %a %a" + n + (fun ppf -> Data_encoding.Json.print_error ppf) + exn2 + Data_encoding.Json.pp + j + | _ -> + failwith + "Invalid transfer at index %i: %a" + n + (fun ppf -> Data_encoding.Json.print_error ppf) + exn2 ) + | _ -> + failwith + "Invalid transfer file: %a %a" + (fun ppf -> Data_encoding.Json.print_error ppf) + exn + Data_encoding.Json.pp + operations_json )); + command + ~group + ~desc:"Transfer tokens / call a smart contract." + (args15 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + arg_arg + no_print_source_flag + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg + entrypoint_arg) + ( prefixes ["transfer"] + @@ tez_param ~name:"qty" ~desc:"amount taken from source" + @@ prefix "from" + @@ ContractAlias.destination_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefix "to" + @@ ContractAlias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + arg, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap, + entrypoint ) + amount + (_, source) + (_, destination) + cctxt -> + transfer_command + amount + source + destination + cctxt + ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + arg, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap, + entrypoint )); + command + ~group + ~desc:"Call a smart contract (same as 'transfer 0')." + (args15 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + arg_arg + no_print_source_flag + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg + entrypoint_arg) + ( prefixes ["call"] + @@ ContractAlias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ prefix "from" + @@ ContractAlias.destination_param + ~name:"src" + ~desc:"name of the source contract" + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + arg, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap, + entrypoint ) + (_, destination) + (_, source) + cctxt -> + let amount = Tez.zero in + transfer_command + amount + source + destination + cctxt + ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + arg, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap, + entrypoint )); + command + ~group + ~desc:"Reveal the public key of the contract manager." + (args9 + fee_arg + dry_run_switch + verbose_signing_switch + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg) + ( prefixes ["reveal"; "key"; "for"] + @@ ContractAlias.alias_param + ~name:"src" + ~desc:"name of the source contract" + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + (_, source) + cctxt -> + match Contract.is_implicit source with + | None -> + failwith "only implicit accounts can be revealed" + | Some source -> + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + reveal + cctxt + ~dry_run + ~verbose_signing + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~source + ?fee + ~src_pk + ~src_sk + ~fee_parameter + () + >>=? fun _res -> return_unit); + command + ~group + ~desc:"Register the public key hash as a delegate." + (args9 + fee_arg + dry_run_switch + verbose_signing_switch + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg) + ( prefixes ["register"; "key"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["as"; "delegate"] + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + src_pkh + cctxt -> + Client_keys.get_key cctxt src_pkh + >>=? fun (_, src_pk, src_sk) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + register_as_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~fee_parameter + ~verbose_signing + ?fee + ~manager_sk:src_sk + src_pk + >>= function + | Ok _ -> + return_unit + | Error [Environment.Ecoproto_error Delegate_storage.Active_delegate] + -> + cctxt#message "Delegate already activated." + >>= fun () -> return_unit + | Error el -> + Lwt.return_error el) ] + @ ( match network with + | Some `Mainnet -> + [] + | Some `Testnet | None -> + [ command + ~group + ~desc:"Register and activate an Alphanet/Zeronet faucet account." + (args2 (Secret_key.force_switch ()) encrypted_switch) + ( prefixes ["activate"; "account"] + @@ Secret_key.fresh_alias_param + @@ prefixes ["with"] + @@ param + ~name:"activation_key" + ~desc: + "Activate an Alphanet/Zeronet faucet account from the JSON \ + (file or directly inlined)." + json_file_or_text_parameter + @@ stop ) + (fun (force, encrypted) name activation_json cctxt -> + Secret_key.of_fresh cctxt force name + >>=? fun name -> + match + Data_encoding.Json.destruct + Client_proto_context.activation_key_encoding + activation_json + with + | exception (Data_encoding.Json.Cannot_destruct _ as exn) -> + Format.kasprintf + (fun s -> failwith "%s" s) + "Invalid activation file: %a %a" + (fun ppf -> Data_encoding.Json.print_error ppf) + exn + Data_encoding.Json.pp + activation_json + | key -> + activate_account + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~encrypted + ~force + key + name + >>=? fun _res -> return_unit) ] ) + @ ( match network with + | Some `Testnet | None -> + [] + | Some `Mainnet -> + [ command + ~group + ~desc:"Activate a fundraiser account." + (args1 dry_run_switch) + ( prefixes ["activate"; "fundraiser"; "account"] + @@ Public_key_hash.alias_param + @@ prefixes ["with"] + @@ param + ~name:"code" + (Clic.parameter (fun _ctx code -> + protect (fun () -> + return + (Blinded_public_key_hash.activation_code_of_hex + code)))) + ~desc:"Activation code obtained from the Tezos foundation." + @@ stop ) + (fun dry_run (name, _pkh) code cctxt -> + activate_existing_account + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + name + code + >>=? fun _res -> return_unit) ] ) + @ [ command + ~desc:"Wait until an operation is included in a block" + (args3 + (default_arg + ~long:"confirmations" + ~placeholder:"num_blocks" + ~doc: + "wait until 'N' additional blocks after the operation appears \ + in the considered chain" + ~default:"0" + non_negative_param) + (default_arg + ~long:"check-previous" + ~placeholder:"num_blocks" + ~doc:"number of previous blocks to check" + ~default:"10" + non_negative_param) + (arg + ~long:"branch" + ~placeholder:"block_hash" + ~doc: + "hash of the oldest block where we should look for the \ + operation" + block_hash_param)) + ( prefixes ["wait"; "for"] + @@ param + ~name:"operation" + ~desc:"Operation to be included" + (parameter (fun _ x -> + match Operation_hash.of_b58check_opt x with + | None -> + Error_monad.failwith "Invalid operation hash: '%s'" x + | Some hash -> + return hash)) + @@ prefixes ["to"; "be"; "included"] + @@ stop ) + (fun (confirmations, predecessors, branch) + operation_hash + (ctxt : Protocol_client_context.full) -> + Client_confirmations.wait_for_operation_inclusion + ctxt + ~chain:ctxt#chain + ~confirmations + ~predecessors + ?branch + operation_hash + >>=? fun _ -> return_unit); + command + ~desc:"Get receipt for past operation" + (args1 + (default_arg + ~long:"check-previous" + ~placeholder:"num_blocks" + ~doc:"number of previous blocks to check" + ~default:"10" + non_negative_param)) + ( prefixes ["get"; "receipt"; "for"] + @@ param + ~name:"operation" + ~desc:"Operation to be looked up" + (parameter (fun _ x -> + match Operation_hash.of_b58check_opt x with + | None -> + Error_monad.failwith "Invalid operation hash: '%s'" x + | Some hash -> + return hash)) + @@ stop ) + (fun predecessors operation_hash (ctxt : Protocol_client_context.full) -> + display_receipt_for_operation + ctxt + ~chain:ctxt#chain + ~predecessors + operation_hash + >>=? fun _ -> return_unit); + command + ~group:binary_description + ~desc:"Describe unsigned block header" + no_options + (fixed ["describe"; "unsigned"; "block"; "header"]) + (fun () (cctxt : Protocol_client_context.full) -> + cctxt#message + "%a" + Data_encoding.Binary_schema.pp + (Data_encoding.Binary.describe + Alpha_context.Block_header.unsigned_encoding) + >>= fun () -> return_unit); + command + ~group:binary_description + ~desc:"Describe unsigned block header" + no_options + (fixed ["describe"; "unsigned"; "operation"]) + (fun () (cctxt : Protocol_client_context.full) -> + cctxt#message + "%a" + Data_encoding.Binary_schema.pp + (Data_encoding.Binary.describe + Alpha_context.Operation.unsigned_encoding) + >>= fun () -> return_unit); + command + ~group + ~desc:"Submit protocol proposals" + (args3 + dry_run_switch + verbose_signing_switch + (switch + ~doc: + "Do not fail when the checks that try to prevent the user \ + from shooting themselves in the foot do." + ~long:"force" + ())) + ( prefixes ["submit"; "proposals"; "for"] + @@ ContractAlias.destination_param + ~name:"delegate" + ~desc:"the delegate who makes the proposal" + @@ seq_of_param + (param + ~name:"proposal" + ~desc:"the protocol hash proposal to be submitted" + (parameter (fun _ x -> + match Protocol_hash.of_b58check_opt x with + | None -> + Error_monad.failwith "Invalid proposal hash: '%s'" x + | Some hash -> + return hash))) ) + (fun (dry_run, verbose_signing, force) + (_name, source) + proposals + (cctxt : Protocol_client_context.full) -> + match Contract.is_implicit source with + | None -> + failwith "only implicit accounts can submit proposals" + | Some src_pkh -> ( + Client_keys.get_key cctxt src_pkh + >>=? fun (src_name, _src_pk, src_sk) -> + get_period_info + (* Find period info of the successor, because the operation will + be injected on the next block at the earliest *) + ~successor:true + ~chain:cctxt#chain + ~block:cctxt#block + cctxt + >>=? fun info -> + ( match info.current_period_kind with + | Proposal -> + return_unit + | _ -> + cctxt#error "Not in a proposal period" ) + >>=? fun () -> + Shell_services.Protocol.list cctxt + >>=? fun known_protos -> + get_proposals ~chain:cctxt#chain ~block:cctxt#block cctxt + >>=? fun known_proposals -> + Alpha_services.Voting.listings cctxt (cctxt#chain, cctxt#block) + >>=? fun listings -> + (* for a proposal to be valid it must either a protocol that was already + proposed by somebody else or a protocol known by the node, because + the user is the first proposer and just injected it with + tezos-admin-client *) + let check_proposals proposals : bool tzresult Lwt.t = + let n = List.length proposals in + let errors = ref [] in + let error ppf = + Format.kasprintf (fun s -> errors := s :: !errors) ppf + in + if n = 0 then error "Empty proposal list." ; + if n > Constants.fixed.max_proposals_per_delegate then + error + "Too many proposals: %d > %d." + n + Constants.fixed.max_proposals_per_delegate ; + ( match + Base.List.find_all_dups + ~compare:Protocol_hash.compare + proposals + with + | [] -> + () + | dups -> + error + "There %s: %a." + ( if List.length dups = 1 then "is a duplicate proposal" + else "are duplicate proposals" ) + Format.( + pp_print_list + ~pp_sep:(fun ppf () -> pp_print_string ppf ", ") + Protocol_hash.pp) + dups ) ; + List.iter + (fun (p : Protocol_hash.t) -> + if + List.mem p known_protos + || Environment.Protocol_hash.Map.mem p known_proposals + then () + else + error + "Protocol %a is not a known proposal." + Protocol_hash.pp + p) + proposals ; + if + not + (List.exists + (fun (pkh, _) -> + Signature.Public_key_hash.equal pkh src_pkh) + listings) + then + error + "Public-key-hash `%a` from account `%s` does not appear \ + to have voting rights." + Signature.Public_key_hash.pp + src_pkh + src_name ; + if !errors <> [] then + cctxt#message + "There %s with the submission:%t" + ( if List.length !errors = 1 then "is an issue" + else "are issues" ) + Format.( + fun ppf -> + pp_print_cut ppf () ; + pp_open_vbox ppf 0 ; + List.iter + (fun msg -> + pp_open_hovbox ppf 2 ; + pp_print_string ppf "* " ; + pp_print_text ppf msg ; + pp_close_box ppf () ; + pp_print_cut ppf ()) + !errors ; + pp_close_box ppf ()) + >>= fun () -> return_false + else return_true + in + check_proposals proposals + >>=? fun all_valid -> + ( if all_valid then cctxt#message "All proposals are valid." + else if force then + cctxt#message + "Some proposals are not valid, but `--force` was used." + else + cctxt#error "Submission failed because of invalid proposals." + ) + >>= fun () -> + submit_proposals + ~dry_run + ~verbose_signing + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~src_sk + src_pkh + proposals + >>= function + | Ok _res -> + return_unit + | Error errs -> + ( match errs with + | [ Unregistered_error + (`O + [("kind", `String "generic"); ("error", `String msg)]) + ] -> + cctxt#message + "Error:@[@.%a@]" + Format.pp_print_text + ( String.split_on_char ' ' msg + |> List.filter (function + | "" | "\n" -> + false + | _ -> + true) + |> String.concat " " + |> String.map (function '\n' | '\t' -> ' ' | c -> c) ) + | el -> + cctxt#message "Error:@ %a" pp_print_error el ) + >>= fun () -> failwith "Failed to submit proposals" )); + command + ~group + ~desc:"Submit a ballot" + (args2 verbose_signing_switch dry_run_switch) + ( prefixes ["submit"; "ballot"; "for"] + @@ ContractAlias.destination_param + ~name:"delegate" + ~desc:"the delegate who votes" + @@ param + ~name:"proposal" + ~desc:"the protocol hash proposal to vote for" + (parameter (fun _ x -> + match Protocol_hash.of_b58check_opt x with + | None -> + failwith "Invalid proposal hash: '%s'" x + | Some hash -> + return hash)) + @@ param + ~name:"ballot" + ~desc:"the ballot value (yea/yay, nay, or pass)" + (parameter + ~autocomplete:(fun _ -> return ["yea"; "nay"; "pass"]) + (fun _ s -> + (* We should have [Vote.of_string]. *) + match String.lowercase_ascii s with + | "yay" | "yea" -> + return Vote.Yay + | "nay" -> + return Vote.Nay + | "pass" -> + return Vote.Pass + | s -> + failwith "Invalid ballot: '%s'" s)) + @@ stop ) + (fun (verbose_signing, dry_run) + (_name, source) + proposal + ballot + (cctxt : Protocol_client_context.full) -> + match Contract.is_implicit source with + | None -> + failwith "only implicit accounts can submit ballot" + | Some src_pkh -> + Client_keys.get_key cctxt src_pkh + >>=? fun (_src_name, _src_pk, src_sk) -> + get_period_info + (* Find period info of the successor, because the operation will + be injected on the next block at the earliest *) + ~successor:true + ~chain:cctxt#chain + ~block:cctxt#block + cctxt + >>=? fun info -> + ( match info.current_period_kind with + | Exploration | Promotion -> + return_unit + | _ -> + cctxt#error "Not in Exploration or Promotion period" ) + >>=? fun () -> + submit_ballot + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~src_sk + src_pkh + ~verbose_signing + ~dry_run + proposal + ballot + >>=? fun _res -> return_unit); + command + ~group + ~desc:"Summarize the current voting period" + no_options + (fixed ["show"; "voting"; "period"]) + (fun () (cctxt : Protocol_client_context.full) -> + get_period_info ~chain:cctxt#chain ~block:cctxt#block cctxt + >>=? fun info -> + cctxt#message + "Current period: %a\nBlocks remaining until end of period: %ld" + Data_encoding.Json.pp + (Data_encoding.Json.construct + Alpha_context.Voting_period.kind_encoding + info.current_period_kind) + info.remaining + >>= fun () -> + Shell_services.Protocol.list cctxt + >>=? fun known_protos -> + get_proposals ~chain:cctxt#chain ~block:cctxt#block cctxt + >>=? fun props -> + let ranks = + Environment.Protocol_hash.Map.bindings props + |> List.sort (fun (_, v1) (_, v2) -> Int32.(compare v2 v1)) + in + let print_proposal = function + | None -> + cctxt#message "The current proposal has already been cleared." + (* The proposal is cleared on the last block of adoption period, and + also on the last block of the exploration and promotion + periods when the proposal is not approved *) + | Some proposal -> + cctxt#message "Current proposal: %a" Protocol_hash.pp proposal + in + match info.current_period_kind with + | Proposal -> + (* the current proposals are cleared on the last block of the + proposal period *) + if info.remaining <> 0l then + cctxt#answer + "Current proposals:%t" + Format.( + fun ppf -> + pp_print_cut ppf () ; + pp_open_vbox ppf 0 ; + List.iter + (fun (p, w) -> + fprintf + ppf + "* %a %ld (%sknown by the node)@." + Protocol_hash.pp + p + w + (if List.mem p known_protos then "" else "not ")) + ranks ; + pp_close_box ppf ()) + >>= fun () -> return_unit + else + cctxt#message "The proposals have already been cleared." + >>= fun () -> return_unit + | Exploration | Promotion -> + print_proposal info.current_proposal + >>= fun () -> + (* the ballots are cleared on the last block of these periods *) + if info.remaining <> 0l then + get_ballots_info ~chain:cctxt#chain ~block:cctxt#block cctxt + >>=? fun ballots_info -> + cctxt#answer + "Ballots: %a@,\ + Current participation %.2f%%, necessary quorum %.2f%%@,\ + Current in favor %ld, needed supermajority %ld" + Data_encoding.Json.pp + (Data_encoding.Json.construct + Vote.ballots_encoding + ballots_info.ballots) + (Int32.to_float ballots_info.participation /. 100.) + (Int32.to_float ballots_info.current_quorum /. 100.) + ballots_info.ballots.yay + ballots_info.supermajority + >>= fun () -> return_unit + else + cctxt#message "The ballots have already been cleared." + >>= fun () -> return_unit + | Cooldown -> + print_proposal info.current_proposal >>= fun () -> return_unit + | Adoption -> + print_proposal info.current_proposal >>= fun () -> return_unit) + ] diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_contracts_commands.ml b/src/proto_009_PsFLoren/lib_client_commands/client_proto_contracts_commands.ml new file mode 100644 index 0000000000000000000000000000000000000000..bb1bea6b3de881d07dfa5a0e95d85ce3e9936478 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_contracts_commands.ml @@ -0,0 +1,87 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Client_proto_contracts + +let group = + { + Clic.name = "contracts"; + title = "Commands for managing the record of known contracts"; + } + +let commands () = + let open Clic in + [ command + ~group + ~desc:"Add a contract to the wallet." + (args1 (RawContractAlias.force_switch ())) + ( prefixes ["remember"; "contract"] + @@ RawContractAlias.fresh_alias_param @@ RawContractAlias.source_param + @@ stop ) + (fun force name hash cctxt -> + RawContractAlias.of_fresh cctxt force name + >>=? fun name -> RawContractAlias.add ~force cctxt name hash); + command + ~group + ~desc:"Remove a contract from the wallet." + no_options + (prefixes ["forget"; "contract"] @@ RawContractAlias.alias_param @@ stop) + (fun () (name, _) cctxt -> RawContractAlias.del cctxt name); + command + ~group + ~desc:"Lists all known contracts in the wallet." + no_options + (fixed ["list"; "known"; "contracts"]) + (fun () (cctxt : Protocol_client_context.full) -> + list_contracts cctxt + >>=? fun contracts -> + List.iter_es + (fun (prefix, alias, contract) -> + cctxt#message + "%s%s: %s" + prefix + alias + (Contract.to_b58check contract) + >>= return) + contracts); + command + ~group + ~desc:"Forget the entire wallet of known contracts." + (args1 (RawContractAlias.force_switch ())) + (fixed ["forget"; "all"; "contracts"]) + (fun force cctxt -> + fail_unless force (failure "this can only used with option -force") + >>=? fun () -> RawContractAlias.set cctxt []); + command + ~group + ~desc:"Display a contract from the wallet." + no_options + ( prefixes ["show"; "known"; "contract"] + @@ RawContractAlias.alias_param @@ stop ) + (fun () (_, contract) (cctxt : Protocol_client_context.full) -> + cctxt#message "%a\n%!" Contract.pp contract >>= fun () -> return_unit) + ] diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_mockup_commands.ml b/src/proto_009_PsFLoren/lib_client_commands/client_proto_mockup_commands.ml new file mode 100644 index 0000000000000000000000000000000000000000..d8bae3e68ec32d91c2d9bf333afa7da910f14ad1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_mockup_commands.ml @@ -0,0 +1,83 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Tezos_clic + +let protocol_constants_arg = + Clic.arg + ~doc:"a JSON file that contains protocol constants to set." + ~long:"protocol-constants" + ~placeholder:"path" + (Clic.parameter (fun _ x -> return x)) + +let bootstrap_accounts_arg = + Clic.arg + ~doc: + "a JSON file that contains definitions of bootstrap accounts to create." + ~long:"bootstrap-accounts" + ~placeholder:"path" + (Clic.parameter (fun _ x -> return x)) + +let asynchronous_flag = + Clic.switch + ~long:"asynchronous" + ~doc:"put operations in mempool and require baking to include in the chain" + () + +let load_json_file (cctxt : Protocol_client_context.full) json_file = + match json_file with + | None -> + return None + | Some filename -> + cctxt#read_file filename + >>=? fun json_string -> + return (Some (Ezjsonm.from_string json_string :> Data_encoding.json)) + +let create_mockup_command_handler + (constants_overrides_file, bootstrap_accounts_file, asynchronous) + (cctxt : Protocol_client_context.full) = + load_json_file cctxt constants_overrides_file + >>=? fun constants_overrides_json -> + load_json_file cctxt bootstrap_accounts_file + >>=? fun bootstrap_accounts_json -> + Tezos_mockup.Persistence.create_mockup + ~cctxt:(cctxt :> Tezos_client_base.Client_context.full) + ~protocol_hash:Protocol.hash + ~constants_overrides_json + ~bootstrap_accounts_json + ~asynchronous + >>=? fun () -> + Tezos_mockup_commands.Mockup_wallet.populate cctxt bootstrap_accounts_file + +let create_mockup_command : Protocol_client_context.full Clic.command = + let open Clic in + command + ~group:Tezos_mockup_commands.Mockup_commands.group + ~desc:"Create a mockup environment." + (args3 protocol_constants_arg bootstrap_accounts_arg asynchronous_flag) + (prefixes ["create"; "mockup"] @@ stop) + create_mockup_command_handler + +let commands () = [create_mockup_command] diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_mockup_commands.mli b/src/proto_009_PsFLoren/lib_client_commands/client_proto_mockup_commands.mli new file mode 100644 index 0000000000000000000000000000000000000000..765437d4365e0282cc34f2507dda5b32c8e06d0a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_mockup_commands.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val commands : unit -> Protocol_client_context.full Clic.command list diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_multisig_commands.ml b/src/proto_009_PsFLoren/lib_client_commands/client_proto_multisig_commands.ml new file mode 100644 index 0000000000000000000000000000000000000000..62f8612a8bf3edee90b3dc66336ff4af40975980 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_multisig_commands.ml @@ -0,0 +1,904 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let group = + { + Clic.name = "multisig"; + title = "Commands for managing a multisig smart contract"; + } + +let threshold_param () = + Clic.param + ~name:"threshold" + ~desc:"Number of required signatures" + Client_proto_args.int_parameter + +let public_key_param () = + Client_keys.Public_key.source_param + ~name:"key" + ~desc:"Each signer of the multisig contract" + +let secret_key_param () = + Client_keys.Secret_key.source_param + ~name:"key" + ~desc: + "Secret key corresponding to one of the public keys stored on the \ + multisig contract" + +let signature_param () = + Clic.param + ~name:"signature" + ~desc:"Each signer of the multisig contract" + Client_proto_args.signature_parameter + +let bytes_only_switch = + Clic.switch + ~long:"bytes-only" + ~doc:"return only the byte sequence to be signed" + () + +let bytes_param ~name ~desc = + Clic.param ~name ~desc Client_proto_args.bytes_parameter + +let transfer_options = + Clic.args13 + Client_proto_args.fee_arg + Client_proto_context_commands.dry_run_switch + Client_proto_context_commands.verbose_signing_switch + Client_proto_args.gas_limit_arg + Client_proto_args.storage_limit_arg + Client_proto_args.counter_arg + Client_proto_args.no_print_source_flag + Client_proto_args.minimal_fees_arg + Client_proto_args.minimal_nanotez_per_byte_arg + Client_proto_args.minimal_nanotez_per_gas_unit_arg + Client_proto_args.force_low_fee_arg + Client_proto_args.fee_cap_arg + Client_proto_args.burn_cap_arg + +let prepare_command_display prepared_command bytes_only = + if bytes_only then + Format.printf + "0x%a@." + Hex.pp + (Hex.of_bytes prepared_command.Client_proto_multisig.bytes) + else + Format.printf + "%a@.%a@.%a@.%a@." + (fun ppf x -> + Format.fprintf ppf "Bytes to sign: '0x%a'" Hex.pp (Hex.of_bytes x)) + prepared_command.Client_proto_multisig.bytes + (fun ppf x -> + Format.fprintf + ppf + "Blake 2B Hash: '%s'" + (Base58.raw_encode Blake2B.(hash_bytes [x] |> to_string))) + prepared_command.Client_proto_multisig.bytes + (fun ppf z -> + Format.fprintf + ppf + "Threshold (number of signatures required): %s" + (Z.to_string z)) + prepared_command.Client_proto_multisig.threshold + (fun ppf -> + Format.fprintf + ppf + "@[<2>Public keys of the signers:@ %a@]" + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf "@ ") + Signature.Public_key.pp)) + prepared_command.Client_proto_multisig.keys + +let commands () : #Protocol_client_context.full Clic.command list = + Clic. + [ command + ~group + ~desc:"Originate a new multisig contract." + (args14 + Client_proto_args.fee_arg + Client_proto_context_commands.dry_run_switch + Client_proto_args.gas_limit_arg + Client_proto_args.storage_limit_arg + Client_proto_args.delegate_arg + (Client_keys.force_switch ()) + Client_proto_args.no_print_source_flag + Client_proto_args.minimal_fees_arg + Client_proto_args.minimal_nanotez_per_byte_arg + Client_proto_args.minimal_nanotez_per_gas_unit_arg + Client_proto_args.force_low_fee_arg + Client_proto_args.fee_cap_arg + Client_proto_context_commands.verbose_signing_switch + Client_proto_args.burn_cap_arg) + ( prefixes ["deploy"; "multisig"] + @@ Client_proto_contracts.RawContractAlias.fresh_alias_param + ~name:"new_multisig" + ~desc:"name of the new multisig contract" + @@ prefix "transferring" + @@ Client_proto_args.tez_param + ~name:"qty" + ~desc:"amount taken from source" + @@ prefix "from" + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefixes ["with"; "threshold"] + @@ threshold_param () + @@ prefixes ["on"; "public"; "keys"] + @@ seq_of_param (public_key_param ()) ) + (fun ( fee, + dry_run, + gas_limit, + storage_limit, + delegate, + force, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + verbose_signing, + burn_cap ) + alias_name + balance + (_, source) + threshold + keys + (cctxt : #Protocol_client_context.full) -> + Client_proto_contracts.RawContractAlias.of_fresh + cctxt + force + alias_name + >>=? fun alias_name -> + match Contract.is_implicit source with + | None -> + failwith + "only implicit accounts can be the source of an origination" + | Some source -> ( + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + List.map_es + (fun (pk_uri, _) -> Client_keys.public_key pk_uri) + keys + >>=? fun keys -> + Client_proto_multisig.originate_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ?fee + ?gas_limit + ?storage_limit + ~verbose_signing + ~delegate + ~threshold:(Z.of_int threshold) + ~keys + ~balance + ~source + ~src_pk + ~src_sk + ~fee_parameter + () + >>= fun errors -> + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"multisig origination simulation failed" + cctxt + errors + >>= function + | None -> + return_unit + | Some (_res, contract) -> + if dry_run then return_unit + else + Client_proto_context.save_contract + ~force + cctxt + alias_name + contract + >>=? fun () -> return_unit )); + command + ~group + ~desc: + "Display the threshold, public keys, and byte sequence to sign for \ + a multisigned transfer." + (args1 bytes_only_switch) + ( prefixes ["prepare"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefix "transferring" + @@ Client_proto_args.tez_param + ~name:"qty" + ~desc:"amount taken from source" + @@ prefix "to" + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ stop ) + (fun bytes_only + (_, multisig_contract) + amount + (_, destination) + (cctxt : #Protocol_client_context.full) -> + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Transfer (amount, destination)) + () + >>=? fun prepared_command -> + return @@ prepare_command_display prepared_command bytes_only); + command + ~group + ~desc: + "Display the threshold, public keys, and byte sequence to sign for \ + a multisigned delegate change." + (args1 bytes_only_switch) + ( prefixes ["prepare"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["setting"; "delegate"; "to"] + @@ Client_keys.Public_key_hash.source_param + ~name:"dlgt" + ~desc:"new delegate of the new multisig contract" + @@ stop ) + (fun bytes_only + (_, multisig_contract) + new_delegate + (cctxt : #Protocol_client_context.full) -> + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate (Some new_delegate)) + () + >>=? fun prepared_command -> + return @@ prepare_command_display prepared_command bytes_only); + command + ~group + ~desc: + "Display the threshold, public keys, and byte sequence to sign for \ + a multisigned delegate withdraw." + (args1 bytes_only_switch) + ( prefixes ["prepare"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["withdrawing"; "delegate"] + @@ stop ) + (fun bytes_only + (_, multisig_contract) + (cctxt : #Protocol_client_context.full) -> + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate None) + () + >>=? fun prepared_command -> + return @@ prepare_command_display prepared_command bytes_only); + command + ~group + ~desc: + "Display the threshold, public keys, and byte sequence to sign for \ + a multisigned change of keys and threshold." + (args1 bytes_only_switch) + ( prefixes ["prepare"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["setting"; "threshold"; "to"] + @@ threshold_param () + @@ prefixes ["and"; "public"; "keys"; "to"] + @@ seq_of_param (public_key_param ()) ) + (fun bytes_only + (_, multisig_contract) + new_threshold + new_keys + (cctxt : #Protocol_client_context.full) -> + List.map_es + (fun (pk_uri, _) -> Client_keys.public_key pk_uri) + new_keys + >>=? fun keys -> + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action: + (Client_proto_multisig.Change_keys (Z.of_int new_threshold, keys)) + () + >>=? fun prepared_command -> + return @@ prepare_command_display prepared_command bytes_only); + command + ~group + ~desc:"Sign a transaction for a multisig contract." + no_options + ( prefixes ["sign"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefix "transferring" + @@ Client_proto_args.tez_param + ~name:"qty" + ~desc:"amount taken from source" + @@ prefix "to" + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ prefixes ["using"; "secret"; "key"] + @@ secret_key_param () @@ stop ) + (fun () + (_, multisig_contract) + amount + (_, destination) + sk + (cctxt : #Protocol_client_context.full) -> + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Transfer (amount, destination)) + () + >>=? fun prepared_command -> + Client_keys.sign cctxt sk prepared_command.bytes + >>=? fun signature -> + return @@ Format.printf "%a@." Signature.pp signature); + command + ~group + ~desc:"Sign a delegate change for a multisig contract." + no_options + ( prefixes ["sign"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["setting"; "delegate"; "to"] + @@ Client_keys.Public_key_hash.source_param + ~name:"dlgt" + ~desc:"new delegate of the new multisig contract" + @@ prefixes ["using"; "secret"; "key"] + @@ secret_key_param () @@ stop ) + (fun () + (_, multisig_contract) + delegate + sk + (cctxt : #Protocol_client_context.full) -> + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate (Some delegate)) + () + >>=? fun prepared_command -> + Client_keys.sign cctxt sk prepared_command.bytes + >>=? fun signature -> + return @@ Format.printf "%a@." Signature.pp signature); + command + ~group + ~desc:"Sign a delegate withdraw for a multisig contract." + no_options + ( prefixes ["sign"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["withdrawing"; "delegate"] + @@ prefixes ["using"; "secret"; "key"] + @@ secret_key_param () @@ stop ) + (fun () + (_, multisig_contract) + sk + (cctxt : #Protocol_client_context.full) -> + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate None) + () + >>=? fun prepared_command -> + Client_keys.sign cctxt sk prepared_command.bytes + >>=? fun signature -> + return @@ Format.printf "%a@." Signature.pp signature); + command + ~group + ~desc: + "Sign a change of public keys and threshold for a multisig contract." + no_options + ( prefixes ["sign"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["using"; "secret"; "key"] + @@ secret_key_param () + @@ prefixes ["setting"; "threshold"; "to"] + @@ threshold_param () + @@ prefixes ["and"; "public"; "keys"; "to"] + @@ seq_of_param (public_key_param ()) ) + (fun () + (_, multisig_contract) + sk + new_threshold + new_keys + (cctxt : #Protocol_client_context.full) -> + List.map_es + (fun (pk_uri, _) -> Client_keys.public_key pk_uri) + new_keys + >>=? fun keys -> + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action: + (Client_proto_multisig.Change_keys (Z.of_int new_threshold, keys)) + () + >>=? fun prepared_command -> + Client_keys.sign cctxt sk prepared_command.bytes + >>=? fun signature -> + return @@ Format.printf "%a@." Signature.pp signature); + command + ~group + ~desc:"Transfer tokens using a multisig contract." + transfer_options + ( prefixes ["from"; "multisig"; "contract"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name/literal of the multisig contract" + @@ prefix "transfer" + @@ Client_proto_args.tez_param + ~name:"qty" + ~desc:"amount taken from the multisig contract" + @@ prefix "to" + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ prefixes ["on"; "behalf"; "of"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ()) ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + (_, multisig_contract) + amount + (_, destination) + (_, source) + signatures + (cctxt : #Protocol_client_context.full) -> + match Contract.is_implicit source with + | None -> + failwith + "only implicit accounts can be the source of a contract call" + | Some source -> ( + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + Client_proto_multisig.call_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~action:(Client_proto_multisig.Transfer (amount, destination)) + ~signatures + ~amount:Tez.zero + ?gas_limit + ?storage_limit + ?counter + () + >>= Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + >>= function + | None -> return_unit | Some (_res, _contracts) -> return_unit )); + command + ~group + ~desc:"Change the delegate of a multisig contract." + transfer_options + ( prefixes ["set"; "delegate"; "of"; "multisig"; "contract"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefix "to" + @@ Client_keys.Public_key_hash.source_param + ~name:"dlgt" + ~desc:"new delegate of the new multisig contract" + @@ prefixes ["on"; "behalf"; "of"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ()) ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + (_, multisig_contract) + delegate + (_, source) + signatures + (cctxt : #Protocol_client_context.full) -> + match Contract.is_implicit source with + | None -> + failwith + "only implicit accounts can be the source of a contract call" + | Some source -> ( + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + Client_proto_multisig.call_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate (Some delegate)) + ~signatures + ~amount:Tez.zero + ?gas_limit + ?storage_limit + ?counter + () + >>= Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + >>= function + | None -> return_unit | Some (_res, _contracts) -> return_unit )); + command + ~group + ~desc:"Withdraw the delegate of a multisig contract." + transfer_options + ( prefixes ["withdraw"; "delegate"; "of"; "multisig"; "contract"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["on"; "behalf"; "of"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ()) ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + (_, multisig_contract) + (_, source) + signatures + (cctxt : #Protocol_client_context.full) -> + match Contract.is_implicit source with + | None -> + failwith + "only implicit accounts can be the source of a contract call" + | Some source -> ( + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + Client_proto_multisig.call_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate None) + ~signatures + ~amount:Tez.zero + ?gas_limit + ?storage_limit + ?counter + () + >>= Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + >>= function + | None -> return_unit | Some (_res, _contracts) -> return_unit )); + command + ~group + ~desc:"Change public keys and threshold for a multisig contract." + transfer_options + ( prefixes ["set"; "threshold"; "of"; "multisig"; "contract"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["to"] + @@ threshold_param () + @@ prefixes ["and"; "public"; "keys"; "to"] + @@ non_terminal_seq (public_key_param ()) ~suffix:["on"; "behalf"; "of"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ()) ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + (_, multisig_contract) + new_threshold + new_keys + (_, source) + signatures + (cctxt : #Protocol_client_context.full) -> + match Contract.is_implicit source with + | None -> + failwith + "only implicit accounts can be the source of a contract call" + | Some source -> ( + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + List.map_es + (fun (pk_uri, _) -> Client_keys.public_key pk_uri) + new_keys + >>=? fun keys -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + Client_proto_multisig.call_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~action: + (Client_proto_multisig.Change_keys + (Z.of_int new_threshold, keys)) + ~signatures + ~amount:Tez.zero + ?gas_limit + ?storage_limit + ?counter + () + >>= Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + >>= function + | None -> return_unit | Some (_res, _contracts) -> return_unit )); + (* This command is no longer necessary as Clic now supports non terminal + lists of parameters, however, it is kept for compatibility. *) + command + ~group + ~desc: + "Run a transaction described by a sequence of bytes on a multisig \ + contract." + transfer_options + ( prefixes ["run"; "transaction"] + @@ bytes_param + ~name:"bytes" + ~desc: + "the sequence of bytes to deserialize as a multisig action, \ + can be obtained by one of the \"prepare multisig \ + transaction\" commands" + @@ prefixes ["on"; "multisig"; "contract"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["on"; "behalf"; "of"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ()) ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + bytes + (_, multisig_contract) + (_, source) + signatures + (cctxt : #Protocol_client_context.full) -> + match Contract.is_implicit source with + | None -> + failwith + "only implicit accounts can be the source of a contract call" + | Some source -> ( + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + Client_proto_multisig.call_multisig_on_bytes + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~bytes + ~signatures + ~amount:Tez.zero + ?gas_limit + ?storage_limit + ?counter + () + >>= Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + >>= function + | None -> return_unit | Some (_res, _contracts) -> return_unit )); + command + ~group + ~desc:"Show the hashes of the supported multisig contracts." + no_options + (fixed ["show"; "supported"; "multisig"; "hashes"]) + (fun () _cctxt -> + Format.printf "Hashes of supported multisig contracts:@." ; + List.iter + (fun h -> + Format.printf + " 0x%a@." + Hex.pp + (Script_expr_hash.to_bytes h |> Hex.of_bytes)) + Client_proto_multisig.known_multisig_hashes ; + return_unit) ] diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_multisig_commands.mli b/src/proto_009_PsFLoren/lib_client_commands/client_proto_multisig_commands.mli new file mode 100644 index 0000000000000000000000000000000000000000..c328ace47c3fc74cb513db621b054369ba75c3d9 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_multisig_commands.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val commands : unit -> Protocol_client_context.full Clic.command list diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_programs_commands.ml b/src/proto_009_PsFLoren/lib_client_commands/client_proto_programs_commands.ml new file mode 100644 index 0000000000000000000000000000000000000000..8b1d667bbd1eaad537bd6c986af05a31be768fca --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_programs_commands.ml @@ -0,0 +1,922 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +let group = + { + Clic.name = "scripts"; + title = "Commands for managing the library of known scripts"; + } + +open Tezos_micheline +open Client_proto_programs +open Client_proto_args +open Client_proto_contracts + +let commands () = + let open Clic in + let show_types_switch = + switch + ~long:"details" + ~short:'v' + ~doc:"show the types of each instruction" + () + in + let emacs_mode_switch = + switch + ~long:"emacs" + ?short:None + ~doc:"output in `michelson-mode.el` compatible format" + () + in + let trace_stack_switch = + switch ~long:"trace-stack" ~doc:"show the stack after each step" () + in + let zero_loc_switch = + switch ~short:'z' ~long:"zero-loc" ~doc:"replace location with \"0\"" () + in + let legacy_switch = + switch + ~long:"legacy" + ~doc:"typecheck in legacy mode as if the data was taken from the chain" + () + in + let amount_arg = + Client_proto_args.tez_arg + ~parameter:"amount" + ~doc:"amount of the transfer in \xEA\x9C\xA9" + ~default:"0.05" + in + let source_arg = + ContractAlias.destination_arg + ~name:"source" + ~doc:"name of the source (i.e. SENDER) contract for the transaction" + () + in + let payer_arg = + ContractAlias.destination_arg + ~name:"payer" + ~doc:"name of the payer (i.e. SOURCE) contract for the transaction" + () + in + let balance_arg = + Client_proto_args.tez_arg + ~parameter:"balance" + ~doc:"balance of run contract in \xEA\x9C\xA9" + ~default:"4_000_000" + in + let custom_gas_flag = + arg + ~long:"gas" + ~short:'G' + ~doc:"Initial quantity of gas for typechecking and execution" + ~placeholder:"gas" + (parameter (fun _ctx str -> + try + let v = Z.of_string str in + assert (Compare.Z.(v >= Z.zero)) ; + return (Alpha_context.Gas.Arith.integral_exn v) + with _ -> failwith "invalid gas limit (must be a positive number)")) + in + let resolve_max_gas cctxt block = function + | None -> + Alpha_services.Constants.all cctxt (cctxt#chain, block) + >>=? fun {parametric = {hard_gas_limit_per_operation; _}; _} -> + return hard_gas_limit_per_operation + | Some gas -> + return gas + in + let parse_expr expr = + Lwt.return @@ Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression expr + in + let data_parameter = parameter (fun _ data -> parse_expr data) in + let data_type_arg = + arg + ~doc:"the given data will be type-checked against this type" + ~short:'t' + ~long:"type" + ~placeholder:"unit" + data_parameter + in + let bytes_parameter ~name ~desc = + param ~name ~desc Client_proto_args.bytes_parameter + in + let signature_parameter = + parameter (fun _cctxt s -> + match Signature.of_b58check_opt s with + | Some s -> + return s + | None -> + failwith "Not given a valid signature") + in + let convert_input_format_param = + param + ~name:"input_format" + ~desc:"format of the input for conversion" + (parameter + ~autocomplete:(fun _ -> return ["michelson"; "json"; "binary"]) + (fun _ s -> + match String.lowercase_ascii s with + | "michelson" -> + return `Michelson + | "json" -> + return `JSON + | "binary" -> + return `Binary + | _ -> + failwith + "invalid input format, expecting one of \"michelson\", \ + \"json\" or \"binary\".")) + in + let convert_output_format_param = + param + ~name:"output_format" + ~desc:"format of the conversion output" + (parameter + ~autocomplete:(fun _ -> + return ["michelson"; "json"; "binary"; "ocaml"]) + (fun _ s -> + match String.lowercase_ascii s with + | "michelson" -> + return `Michelson + | "json" -> + return `JSON + | "binary" -> + return `Binary + | "ocaml" -> + return `OCaml + | _ -> + failwith + "invalid output format, expecting one of \"michelson\", \ + \"json\", \"binary\" or \"ocaml\".")) + in + let file_or_literal_param = + param + ~name:"source" + ~desc:"literal or a path to a file" + (parameter (fun cctxt s -> + cctxt#read_file s + >>= function Ok v -> return v | Error _ -> return s)) + in + [ command + ~group + ~desc:"Lists all scripts in the library." + no_options + (fixed ["list"; "known"; "scripts"]) + (fun () (cctxt : Protocol_client_context.full) -> + Program.load cctxt + >>=? fun list -> + List.iter_s (fun (n, _) -> cctxt#message "%s" n) list + >>= fun () -> return_unit); + command + ~group + ~desc:"Add a script to the library." + (args1 (Program.force_switch ())) + ( prefixes ["remember"; "script"] + @@ Program.fresh_alias_param @@ Program.source_param @@ stop ) + (fun force name hash cctxt -> + Program.of_fresh cctxt force name + >>=? fun name -> Program.add ~force cctxt name hash); + command + ~group + ~desc:"Remove a script from the library." + no_options + (prefixes ["forget"; "script"] @@ Program.alias_param @@ stop) + (fun () (name, _) cctxt -> Program.del cctxt name); + command + ~group + ~desc:"Display a script from the library." + no_options + (prefixes ["show"; "known"; "script"] @@ Program.alias_param @@ stop) + (fun () (_, program) (cctxt : Protocol_client_context.full) -> + Program.to_source program + >>=? fun source -> + cctxt#message "%s\n" source >>= fun () -> return_unit); + command + ~group + ~desc:"Ask the node to run a script." + (args9 + trace_stack_switch + amount_arg + balance_arg + source_arg + payer_arg + no_print_source_flag + custom_gas_flag + entrypoint_arg + (unparsing_mode_arg ~default:"Readable")) + ( prefixes ["run"; "script"] + @@ Program.source_param + @@ prefixes ["on"; "storage"] + @@ param ~name:"storage" ~desc:"the storage data" data_parameter + @@ prefixes ["and"; "input"] + @@ param ~name:"input" ~desc:"the input data" data_parameter + @@ stop ) + (fun ( trace_exec, + amount, + balance, + source, + payer, + no_print_source, + gas, + entrypoint, + unparsing_mode ) + program + storage + input + cctxt -> + let source = Option.map snd source in + let payer = Option.map snd payer in + Lwt.return @@ Micheline_parser.no_parsing_error program + >>=? fun program -> + let show_source = not no_print_source in + if trace_exec then + trace + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~amount + ~balance + ~program + ~storage + ~input + ~unparsing_mode + ?source + ?payer + ?gas + ?entrypoint + () + >>= fun res -> + print_trace_result cctxt ~show_source ~parsed:program res + else + run + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~amount + ~balance + ~program + ~storage + ~input + ~unparsing_mode + ?source + ?payer + ?gas + ?entrypoint + () + >>= fun res -> + print_run_result cctxt ~show_source ~parsed:program res); + command + ~group + ~desc:"Ask the node to typecheck a script." + (args5 + show_types_switch + emacs_mode_switch + no_print_source_flag + custom_gas_flag + legacy_switch) + (prefixes ["typecheck"; "script"] @@ Program.source_param @@ stop) + (fun (show_types, emacs_mode, no_print_source, original_gas, legacy) + program + cctxt -> + match program with + | (program, []) -> + resolve_max_gas cctxt cctxt#block original_gas + >>=? fun original_gas -> + typecheck_program + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~gas:original_gas + ~legacy + program + >>= fun res -> + print_typecheck_result + ~emacs:emacs_mode + ~show_types + ~print_source_on_error:(not no_print_source) + program + res + cctxt + | res_with_errors when emacs_mode -> + cctxt#message + "(@[(types . ())@ (errors . %a)@])" + Michelson_v1_emacs.report_errors + res_with_errors + >>= fun () -> return_unit + | (parsed, errors) -> + cctxt#message + "%a" + (fun ppf () -> + Michelson_v1_error_reporter.report_errors + ~details:(not no_print_source) + ~parsed + ~show_source:(not no_print_source) + ppf + errors) + () + >>= fun () -> cctxt#error "syntax error in program"); + command + ~group + ~desc:"Ask the node to typecheck a data expression." + (args3 no_print_source_flag custom_gas_flag legacy_switch) + ( prefixes ["typecheck"; "data"] + @@ param ~name:"data" ~desc:"the data to typecheck" data_parameter + @@ prefixes ["against"; "type"] + @@ param ~name:"type" ~desc:"the expected type" data_parameter + @@ stop ) + (fun (no_print_source, custom_gas, legacy) data ty cctxt -> + resolve_max_gas cctxt cctxt#block custom_gas + >>=? fun original_gas -> + Client_proto_programs.typecheck_data + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~gas:original_gas + ~legacy + ~data + ~ty + () + >>= function + | Ok gas -> + cctxt#message + "@[Well typed@,Gas remaining: %a@]" + Alpha_context.Gas.pp + gas + >>= fun () -> return_unit + | Error errs -> + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:(not no_print_source) + ?parsed:None) + errs + >>= fun () -> cctxt#error "ill-typed data"); + command + ~group + ~desc: + "Ask the node to pack a data expression.\n\ + The returned hash is the same as what Michelson instruction `PACK` \ + would have produced.\n\ + Also displays the result of hashing this packed data with `BLAKE2B`, \ + `SHA256` or `SHA512` instruction." + (args1 custom_gas_flag) + ( prefixes ["hash"; "data"] + @@ param ~name:"data" ~desc:"the data to hash" data_parameter + @@ prefixes ["of"; "type"] + @@ param ~name:"type" ~desc:"type of the data" data_parameter + @@ stop ) + (fun custom_gas data typ cctxt -> + resolve_max_gas cctxt cctxt#block custom_gas + >>=? fun original_gas -> + Alpha_services.Helpers.Scripts.pack_data + cctxt + (cctxt#chain, cctxt#block) + ~gas:original_gas + ~data:data.expanded + ~ty:typ.expanded + >>= function + | Ok (bytes, remaining_gas) -> + let hash = Script_expr_hash.hash_bytes [bytes] in + cctxt#message + "Raw packed data: 0x%a@,\ + Script-expression-ID-Hash: %a@,\ + Raw Script-expression-ID-Hash: 0x%a@,\ + Ledger Blake2b hash: %s@,\ + Raw Sha256 hash: 0x%a@,\ + Raw Sha512 hash: 0x%a@,\ + Gas remaining: %a" + Hex.pp + (Hex.of_bytes bytes) + Script_expr_hash.pp + hash + Hex.pp + (Hex.of_bytes (Script_expr_hash.to_bytes hash)) + (Base58.raw_encode Blake2B.(hash_bytes [bytes] |> to_string)) + Hex.pp + (Hex.of_bytes (Environment.Raw_hashes.sha256 bytes)) + Hex.pp + (Hex.of_bytes (Environment.Raw_hashes.sha512 bytes)) + Alpha_context.Gas.pp + remaining_gas + >>= fun () -> return_unit + | Error errs -> + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + >>= fun () -> cctxt#error "ill-formed data"); + command + ~group + ~desc: + "Parse a byte sequence (in hexadecimal notation) as a data \ + expression, as per Michelson instruction `UNPACK`." + no_options + ( prefixes ["unpack"; "michelson"; "data"] + @@ bytes_parameter ~name:"bytes" ~desc:"the packed data to parse" + @@ stop ) + (fun () bytes cctxt -> + ( if Bytes.get bytes 0 != '\005' then + failwith + "Not a piece of packed Michelson data (must start with `0x05`)" + else return_unit ) + >>=? fun () -> + (* Remove first byte *) + let bytes = Bytes.sub bytes 1 (Bytes.length bytes - 1) in + match + Data_encoding.Binary.of_bytes_opt + Alpha_context.Script.expr_encoding + bytes + with + | None -> + failwith "Could not decode bytes" + | Some expr -> + cctxt#message "%a" Michelson_v1_printer.print_expr_unwrapped expr + >>= fun () -> return_unit); + command + ~group + ~desc:"Ask the node to normalize a script." + (args1 (unparsing_mode_arg ~default:"Readable")) + (prefixes ["normalize"; "script"] @@ Program.source_param @@ stop) + (fun unparsing_mode program cctxt -> + Lwt.return @@ Micheline_parser.no_parsing_error program + >>=? fun program -> + Alpha_services.Helpers.Scripts.normalize_script + cctxt + (cctxt#chain, cctxt#block) + ~script:program.expanded + ~unparsing_mode + >>= function + | Ok program -> + cctxt#message + "%a" + (fun ppf () -> + (Michelson_v1_printer.print_expr_unwrapped ppf program : unit)) + () + >>= fun () -> return_unit + | Error errs -> + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + >>= fun () -> cctxt#error "ill-typed script"); + command + ~group + ~desc:"Ask the node to normalize a data expression." + (args2 (unparsing_mode_arg ~default:"Readable") legacy_switch) + ( prefixes ["normalize"; "data"] + @@ param + ~name:"data" + ~desc:"the data expression to normalize" + data_parameter + @@ prefixes ["of"; "type"] + @@ param ~name:"type" ~desc:"type of the data expression" data_parameter + @@ stop ) + (fun (unparsing_mode, legacy) data typ cctxt -> + Alpha_services.Helpers.Scripts.normalize_data + cctxt + (cctxt#chain, cctxt#block) + ~legacy + ~data:data.expanded + ~ty:typ.expanded + ~unparsing_mode + >>= function + | Ok expr -> + cctxt#message "%a" Michelson_v1_printer.print_expr_unwrapped expr + >>= fun () -> return_unit + | Error errs -> + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + >>= fun () -> cctxt#error "ill-typed data expression"); + command + ~group + ~desc:"Ask the node to normalize a type." + no_options + ( prefixes ["normalize"; "type"] + @@ param + ~name:"typ" + ~desc:"the Michelson type to normalize" + data_parameter + @@ stop ) + (fun () typ cctxt -> + Plugin.RPC.normalize_type + cctxt + (cctxt#chain, cctxt#block) + ~ty:typ.expanded + >>= function + | Ok expr -> + cctxt#message "%a" Michelson_v1_printer.print_expr_unwrapped expr + >>= fun () -> return_unit + | Error errs -> + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + >>= fun () -> cctxt#error "ill-formed type"); + command + ~group + ~desc: + "Sign a raw sequence of bytes and display it using the format \ + expected by Michelson instruction `CHECK_SIGNATURE`." + no_options + ( prefixes ["sign"; "bytes"] + @@ bytes_parameter ~name:"data" ~desc:"the raw data to sign" + @@ prefixes ["for"] + @@ Client_keys.Secret_key.source_param @@ stop ) + (fun () bytes sk cctxt -> + Client_keys.sign cctxt sk bytes + >>=? fun signature -> + cctxt#message "Signature: %a" Signature.pp signature + >>= fun () -> return_unit); + command + ~group + ~desc: + "Check the signature of a byte sequence as per Michelson instruction \ + `CHECK_SIGNATURE`." + (args1 (switch ~doc:"Use only exit codes" ~short:'q' ~long:"quiet" ())) + ( prefixes ["check"; "that"; "bytes"] + @@ bytes_parameter ~name:"bytes" ~desc:"the signed data" + @@ prefixes ["were"; "signed"; "by"] + @@ Client_keys.Public_key.alias_param ~name:"key" + @@ prefixes ["to"; "produce"] + @@ param + ~name:"signature" + ~desc:"the signature to check" + signature_parameter + @@ stop ) + (fun quiet + bytes + (_, (key_locator, _)) + signature + (cctxt : #Protocol_client_context.full) -> + Client_keys.check key_locator signature bytes + >>=? function + | false -> + cctxt#error "invalid signature" + | true -> + if quiet then return_unit + else + cctxt#message "Signature check successful." + >>= fun () -> return_unit); + command + ~group + ~desc:"Ask the type of an entrypoint of a script." + (args2 emacs_mode_switch no_print_source_flag) + ( prefixes ["get"; "script"; "entrypoint"; "type"; "of"] + @@ string ~name:"entrypoint" ~desc:"the entrypoint to describe" + @@ prefixes ["for"] + @@ Program.source_param @@ stop ) + (fun (emacs_mode, no_print_source) entrypoint program cctxt -> + match program with + | (program, []) -> + entrypoint_type + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + program + ~entrypoint + >>= fun entrypoint_type -> + print_entrypoint_type + ~emacs:emacs_mode + ~show_source:(not no_print_source) + ~parsed:program + ~entrypoint + cctxt + entrypoint_type + | res_with_errors when emacs_mode -> + cctxt#message + "(@[(entrypoint . ())@ (errors . %a)@])" + Michelson_v1_emacs.report_errors + res_with_errors + >>= fun () -> return_unit + | (parsed, errors) -> + cctxt#message + "%a" + (fun ppf () -> + Michelson_v1_error_reporter.report_errors + ~details:(not no_print_source) + ~parsed + ~show_source:(not no_print_source) + ppf + errors) + () + >>= fun () -> cctxt#error "syntax error in program"); + command + ~group + ~desc:"Ask the node to list the entrypoints of a script." + (args2 emacs_mode_switch no_print_source_flag) + ( prefixes ["get"; "script"; "entrypoints"; "for"] + @@ Program.source_param @@ stop ) + (fun (emacs_mode, no_print_source) program cctxt -> + match program with + | (program, []) -> + list_entrypoints + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + program + >>= fun entrypoints -> + print_entrypoints_list + ~emacs:emacs_mode + ~show_source:(not no_print_source) + ~parsed:program + cctxt + entrypoints + | res_with_errors when emacs_mode -> + cctxt#message + "(@[(entrypoints . ())@ (errors . %a)@])" + Michelson_v1_emacs.report_errors + res_with_errors + >>= fun () -> return_unit + | (parsed, errors) -> + cctxt#message + "%a" + (fun ppf () -> + Michelson_v1_error_reporter.report_errors + ~details:(not no_print_source) + ~parsed + ~show_source:(not no_print_source) + ppf + errors) + () + >>= fun () -> cctxt#error "syntax error in program"); + command + ~group + ~desc: + "Ask the node to list the unreachable paths in a script's parameter \ + type." + (args2 emacs_mode_switch no_print_source_flag) + ( prefixes ["get"; "script"; "unreachable"; "paths"; "for"] + @@ Program.source_param @@ stop ) + (fun (emacs_mode, no_print_source) program cctxt -> + match program with + | (program, []) -> + list_unreachables + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + program + >>= fun entrypoints -> + print_unreachables + ~emacs:emacs_mode + ~show_source:(not no_print_source) + ~parsed:program + cctxt + entrypoints + | res_with_errors when emacs_mode -> + cctxt#message + "(@[(entrypoints . ())@ (errors . %a)@])" + Michelson_v1_emacs.report_errors + res_with_errors + >>= fun () -> return_unit + | (parsed, errors) -> + cctxt#message + "%a" + (fun ppf () -> + Michelson_v1_error_reporter.report_errors + ~details:(not no_print_source) + ~parsed + ~show_source:(not no_print_source) + ppf + errors) + () + >>= fun () -> cctxt#error "syntax error in program"); + command + ~group + ~desc:"Ask the node to expand the Michelson macros in a script." + no_options + (prefixes ["expand"; "macros"; "in"] @@ Program.source_param @@ stop) + (fun () program (cctxt : Protocol_client_context.full) -> + Lwt.return @@ Micheline_parser.no_parsing_error program + >>=? fun program -> + cctxt#message + "%a" + (fun ppf () -> + ( Michelson_v1_printer.print_expr_unwrapped ppf program.expanded + : unit )) + () + >>= fun () -> return_unit); + command + ~desc: + "Conversion of Michelson script from Micheline, JSON or binary to \ + Micheline, JSON, binary or OCaml" + (args1 zero_loc_switch) + ( prefixes ["convert"; "script"] + @@ file_or_literal_param @@ prefix "from" @@ convert_input_format_param + @@ prefix "to" @@ convert_output_format_param @@ stop ) + (fun zero_loc + expr_string + from_format + to_format + (cctxt : Protocol_client_context.full) -> + ( match from_format with + | `Michelson -> + let program = Michelson_v1_parser.parse_toplevel expr_string in + Lwt.return @@ Micheline_parser.no_parsing_error program + >>=? fun program -> + typecheck_program + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + program + >>= (function + | Error _ as res -> + print_typecheck_result + ~emacs:false + ~show_types:true + ~print_source_on_error:true + program + res + cctxt + | Ok _ -> + return_unit) + >>=? fun () -> return program.expanded + | `JSON -> ( + match Data_encoding.Json.from_string expr_string with + | Error err -> + cctxt#error "%s" err + | Ok json -> + return + @@ Data_encoding.Json.destruct + Alpha_context.Script.expr_encoding + json ) + | `Binary -> ( + bytes_of_prefixed_string expr_string + >>=? fun bytes -> + match + Data_encoding.Binary.of_bytes_opt + Alpha_context.Script.expr_encoding + bytes + with + | None -> + failwith "Could not decode bytes" + | Some expr -> + return expr ) ) + >>=? fun (expression : Alpha_context.Script.expr) -> + let output = + match to_format with + | `Michelson -> + Micheline_printer.printable + Michelson_v1_primitives.string_of_prim + expression + |> Format.asprintf "%a" Micheline_printer.print_expr + | `JSON -> + Data_encoding.Json.( + construct Alpha_context.Script.expr_encoding expression + |> to_string) + | `Binary -> + Format.asprintf + "0x%s" + ( Data_encoding.Binary.( + to_bytes_exn Alpha_context.Script.expr_encoding expression) + |> Hex.of_bytes |> Hex.show ) + | `OCaml -> + Michelson_v1_printer.micheline_string_of_expression + ~zero_loc + expression + in + cctxt#message "%s" output >>= fun () -> return_unit); + command + ~desc: + "Conversion of Micheline expression from Micheline, JSON or binary to \ + Micheline, JSON, binary or OCaml" + (args2 zero_loc_switch data_type_arg) + ( prefixes ["convert"; "data"] + @@ file_or_literal_param @@ prefix "from" @@ convert_input_format_param + @@ prefix "to" @@ convert_output_format_param @@ stop ) + (fun (zero_loc, data_ty) + data_string + from_format + to_format + (cctxt : Protocol_client_context.full) -> + let micheline_of_expr expr = + Micheline_printer.printable + Michelson_v1_primitives.string_of_prim + expr + |> Format.asprintf "%a" Micheline_printer.print_expr + in + let typecheck_parsed ~data ~ty = + Client_proto_programs.typecheck_data + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~data + ~ty + () + >>= function + | Error errs -> + failwith + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + | Ok _gas -> + return data.expanded + in + let typecheck_expr ~expr ~ty = + let data_string = micheline_of_expr expr in + parse_expr data_string >>=? fun data -> typecheck_parsed ~data ~ty + in + ( match from_format with + | `Michelson -> ( + parse_expr data_string + >>=? fun data -> + match data_ty with + | Some ty -> + typecheck_parsed ~data ~ty + | None -> + return data.expanded ) + | `JSON -> ( + match Data_encoding.Json.from_string data_string with + | Error err -> + cctxt#error "%s" err + | Ok json -> ( + return + @@ Data_encoding.Json.destruct + Alpha_context.Script.expr_encoding + json + >>=? fun expr -> + match data_ty with + | None -> + return expr + | Some ty -> + typecheck_expr ~expr ~ty ) ) + | `Binary -> ( + bytes_of_prefixed_string data_string + >>=? fun bytes -> + match + Data_encoding.Binary.of_bytes_opt + Alpha_context.Script.expr_encoding + bytes + with + | None -> + failwith "Could not decode bytes" + | Some expr -> ( + match data_ty with + | None -> + return expr + | Some ty -> + typecheck_expr ~expr ~ty ) ) ) + >>=? fun (expression : Alpha_context.Script.expr) -> + let output = + match to_format with + | `Michelson -> + micheline_of_expr expression + | `JSON -> + Data_encoding.Json.( + construct Alpha_context.Script.expr_encoding expression + |> to_string) + | `Binary -> + Format.asprintf + "0x%s" + ( Data_encoding.Binary.( + to_bytes_exn Alpha_context.Script.expr_encoding expression) + |> Hex.of_bytes |> Hex.show ) + | `OCaml -> + Michelson_v1_printer.micheline_string_of_expression + ~zero_loc + expression + in + cctxt#message "%s" output >>= fun () -> return_unit) ] diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_programs_commands.mli b/src/proto_009_PsFLoren/lib_client_commands/client_proto_programs_commands.mli new file mode 100644 index 0000000000000000000000000000000000000000..6e352b98be7f9fc04206ab6529ecc94856c9e6bb --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_programs_commands.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val commands : unit -> Protocol_client_context.full Clic.command list diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_utils_commands.ml b/src/proto_009_PsFLoren/lib_client_commands/client_proto_utils_commands.ml new file mode 100644 index 0000000000000000000000000000000000000000..e759ad1826dd3a25e61e1abb38915d5262197c06 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_utils_commands.ml @@ -0,0 +1,112 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Client_proto_utils + +let group = {Clic.name = "utilities"; title = "Utility Commands"} + +let commands () = + let open Clic in + let string_param ~name ~desc = + param ~name ~desc Client_proto_args.string_parameter + in + let block_arg = + default_arg + ~long:"block" + ~short:'b' + ~placeholder:"hash|tag" + ~doc: + "block on which to apply contextual commands (possible tags are \ + 'head' and 'genesis'). Defaults to 'genesis'." + ~default:(Block_services.to_string `Genesis) + (Client_config.block_parameter ()) + in + [ command + ~group + ~desc: + "Sign a message and display it using the failing_noop operation. This \ + operation is not executable in the protocol. Please note that \ + signing/checking an arbitrary message in itself is not sufficient to \ + verify a key ownership" + (args1 block_arg) + ( prefixes ["sign"; "message"] + @@ string_param ~name:"message" ~desc:"message to sign" + @@ prefixes ["for"] + @@ Client_keys.Secret_key.source_param + ~name:"src" + ~desc:"name of the signer contract" + @@ stop ) + (fun block_head message src_sk cctxt -> + Shell_services.Blocks.hash + cctxt + ~chain:cctxt#chain + ~block:block_head + () + >>=? fun block -> + sign_message cctxt ~src_sk ~block ~message + >>=? fun signature -> + cctxt#message "Signature: %a" Signature.pp signature + >>= fun () -> return_unit); + command + ~group + ~desc: + "Check the signature of an arbitrary message using the failing_noop \ + operation. Please note that signing/checking an arbitrary message in \ + itself is not sufficient to verify a key ownership." + (args2 + block_arg + (switch ~doc:"Use only exit codes" ~short:'q' ~long:"quiet" ())) + ( prefixes ["check"; "that"; "message"] + @@ string_param ~name:"message" ~desc:"signed message" + @@ prefixes ["was"; "signed"; "by"] + @@ Client_keys.Public_key.alias_param + ~name:"signer" + ~desc:"name of the signer contract" + @@ prefixes ["to"; "produce"] + @@ param + ~name:"signature" + ~desc:"the signature to check" + Client_proto_args.signature_parameter + @@ stop ) + (fun (block_head, quiet) + message + (_, (key_locator, _)) + signature + (cctxt : #Protocol_client_context.full) -> + Shell_services.Blocks.hash + cctxt + ~chain:cctxt#chain + ~block:block_head + () + >>=? fun block -> + check_message cctxt ~key_locator ~block ~quiet ~message ~signature + >>=? function + | false -> + cctxt#error "invalid signature" + | true -> + if quiet then return_unit + else + cctxt#message "Signature check successful" + >>= fun () -> return_unit) ] diff --git a/src/proto_009_PsFLoren/lib_client_commands/client_proto_utils_commands.mli b/src/proto_009_PsFLoren/lib_client_commands/client_proto_utils_commands.mli new file mode 100644 index 0000000000000000000000000000000000000000..0d38cde9a251134d2f53220954adc89cccdc9afd --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/client_proto_utils_commands.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val commands : unit -> Protocol_client_context.full Clic.command list diff --git a/src/proto_009_PsFLoren/lib_client_commands/dune b/src/proto_009_PsFLoren/lib_client_commands/dune new file mode 100644 index 0000000000000000000000000000000000000000..af0b319d7811e334467305a977b391e0a11068fe --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/dune @@ -0,0 +1,60 @@ +(library + (name tezos_client_009_PsFLoren_commands) + (public_name tezos-client-009-PsFLoren-commands) + (libraries tezos-base + tezos-stdlib-unix + tezos-protocol-009-PsFLoren + tezos-protocol-environment + tezos-shell-services + tezos-mockup + tezos-mockup-registration + tezos-mockup-commands + tezos-client-base-unix + tezos-client-009-PsFLoren + tezos-client-commands + tezos-rpc + tezos-protocol-plugin-009-PsFLoren) + (library_flags (:standard -linkall)) + (modules (:standard \ alpha_commands_registration)) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren + -open Tezos_stdlib_unix + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_009_PsFLoren + -open Tezos_client_commands + -open Tezos_rpc + -open Tezos_client_base_unix + -open Tezos_protocol_plugin_009_PsFLoren))) + +(library + (name tezos_client_009_PsFLoren_commands_registration) + (public_name tezos-client-009-PsFLoren-commands-registration) + (libraries tezos-base + tezos-protocol-009-PsFLoren + tezos-protocol-environment + tezos-shell-services + tezos-client-base + tezos-client-009-PsFLoren + tezos-client-commands + tezos-client-009-PsFLoren-commands + tezos-client-sapling-009-PsFLoren + tezos-rpc + tezos-protocol-plugin-009-PsFLoren) + (library_flags (:standard -linkall)) + (modules alpha_commands_registration) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_009_PsFLoren + -open Tezos_client_commands + -open Tezos_client_009_PsFLoren_commands + -open Tezos_client_sapling_009_PsFLoren + -open Tezos_rpc + -open Tezos_protocol_plugin_009_PsFLoren))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/lib_client_commands/dune-project b/src/proto_009_PsFLoren/lib_client_commands/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..2cbeb8024d793943e132030e2ba8d588f03b5c8d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-client-alpha-commands) diff --git a/src/proto_009_PsFLoren/lib_client_commands/tezos-client-009-PsFLoren-commands-registration.opam b/src/proto_009_PsFLoren/lib_client_commands/tezos-client-009-PsFLoren-commands-registration.opam new file mode 100644 index 0000000000000000000000000000000000000000..23f5dc0ab326a009568b9075243deae729d272e7 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/tezos-client-009-PsFLoren-commands-registration.opam @@ -0,0 +1,25 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-protocol-environment" + "tezos-protocol-009-PsFLoren" + "tezos-shell-services" + "tezos-client-base" + "tezos-client-009-PsFLoren" + "tezos-client-009-PsFLoren-commands" + "tezos-client-sapling-009-PsFLoren" + "tezos-client-commands" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol-specific commands for `tezos-client`" diff --git a/src/proto_009_PsFLoren/lib_client_commands/tezos-client-009-PsFLoren-commands.opam b/src/proto_009_PsFLoren/lib_client_commands/tezos-client-009-PsFLoren-commands.opam new file mode 100644 index 0000000000000000000000000000000000000000..f4f6549d6afc86c8210c52d124ab2fb33bb0b0e4 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_commands/tezos-client-009-PsFLoren-commands.opam @@ -0,0 +1,23 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-protocol-environment" + "tezos-protocol-009-PsFLoren" + "tezos-shell-services" + "tezos-client-base-unix" + "tezos-client-009-PsFLoren" + "tezos-client-commands" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol-specific commands for `tezos-client`" diff --git a/src/proto_009_PsFLoren/lib_client_sapling/.ocamlformat b/src/proto_009_PsFLoren/lib_client_sapling/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_client_sapling/client_sapling_commands.ml b/src/proto_009_PsFLoren/lib_client_sapling/client_sapling_commands.ml new file mode 100644 index 0000000000000000000000000000000000000000..ca3b8647d0594b1fb0e1bbcd1fc2fdd0e92cb182 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/client_sapling_commands.ml @@ -0,0 +1,823 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +open Clic +open Client_keys +open Tezos_sapling.Core.Client + +let json_switch = switch ~long:"json" ~doc:"Use JSON format" () + +let save_json_to_file json file = + let output_channel = open_out_bin file in + let ppf = Format.formatter_of_out_channel output_channel in + Data_encoding.Json.pp ppf json ; + Format.pp_print_flush ppf () ; + close_out output_channel + +let group = + { + Clic.name = "sapling"; + title = "Commands for working with Sapling transactions"; + } + +let keys_of_implicit_account cctxt source = + match Protocol.Alpha_context.Contract.is_implicit source with + | None -> + assert false + | Some src -> + Client_keys.get_key cctxt src >>=? fun (_, pk, sk) -> return (src, pk, sk) + +let viewing_key_of_string s = + let exception Unknown_sapling_address in + let encoding = Viewing_key.address_b58check_encoding in + WithExceptions.Option.to_exn + ~none:Unknown_sapling_address + (Base58.simple_decode encoding s) + +(** All signatures are done with an anti-replay string. + In Tezos' protocol this string is set to be chain_id + KT1. **) +let anti_replay cctxt contract = + Tezos_shell_services.Chain_services.chain_id cctxt ~chain:cctxt#chain () + >>=? fun chain_id -> + let address = Protocol.Alpha_context.Contract.to_b58check contract in + let chain_id = Chain_id.to_b58check chain_id in + return (address ^ chain_id) + +let do_unshield cctxt contract src_name stez dst = + anti_replay cctxt contract + >>=? fun anti_replay -> + Wallet.new_address cctxt src_name None + >>=? fun (src, _, backdst) -> + Context.Client_state.sync_and_scan cctxt contract + >>=? fun contract_state -> + Lwt.return + @@ Context.unshield ~src ~dst ~backdst stez contract_state anti_replay + +let do_shield cctxt ?message contract utez dst = + anti_replay cctxt contract + >>=? fun anti_replay -> + Context.Client_state.sync_and_scan cctxt contract + >>=? fun contract_state -> + let dst = viewing_key_of_string dst in + Context.shield cctxt ~dst ?message utez contract_state anti_replay + +let do_sapling_transfer cctxt ?message contract src_name amount dst = + anti_replay cctxt contract + >>=? fun anti_replay -> + Wallet.new_address cctxt src_name None + >>=? fun (src, _, backdst) -> + Context.Client_state.sync_and_scan cctxt contract + >>=? fun contract_state -> + let dst = viewing_key_of_string dst in + Context.transfer + cctxt + ~src + ~dst + ~backdst + ?message + amount + contract_state + anti_replay + +let message_arg = + let open Clic in + arg + ~long:"message" + ~placeholder:"" + ~doc:"Message for Sapling transaction" + (parameter (fun _ x -> return @@ Bytes.of_string x)) + +let memo_size_arg = + let open Clic in + arg + ~long:"memo-size" + ~placeholder:"memo-size" + ~doc:"Expected length for message of Sapling transaction" + (parameter (fun _ s -> + match + let i = int_of_string s in + assert (i >= 0 && i <= 65535) ; + i + with + | i -> + return i + | exception _ -> + failwith "invalid memo-size (must be between 0 and 65535)")) + +let shield_cmd = + let open Client_proto_args in + let open Client_proto_context_commands in + let open Protocol.Alpha_context in + let open Client_proto_contracts in + command + ~group + ~desc:"Shield tokens from an implicit account to a Sapling address." + (args14 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + no_print_source_flag + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg + message_arg) + ( prefixes ["sapling"; "shield"] + @@ tez_param + ~name:"qty" + ~desc:"Amount taken from transparent wallet of source." + @@ prefix "from" + @@ ContractAlias.destination_param + ~name:"src-tz" + ~desc:"Transparent source account." + @@ prefix "to" + @@ Clic.string ~name:"dst-sap" ~desc:"Sapling address of destination." + @@ prefix "using" + @@ ContractAlias.destination_param + ~name:"sapling contract" + ~desc:"Smart contract to submit this transaction to." + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap, + message ) + amount + (_, source) + sapling_dst + (_contract_name, contract_dst) + cctxt -> + keys_of_implicit_account cctxt source + >>=? fun (pkh, src_pk, src_sk) -> + let open Context in + cctxt#warning + "Shielding %a from %a to %s@ entails a loss of privacy@." + Tez.pp + amount + Contract.pp + source + sapling_dst + >>= fun () -> + do_shield cctxt ?message contract_dst amount sapling_dst + >>=? fun sapling_input -> + let arg = Shielded_tez_contract_input.as_arg sapling_input in + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + Client_proto_context.transfer + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~fee_parameter + ~amount + ~src_pk + ~src_sk + ~destination:contract_dst + ~source:pkh + ~arg + ?confirmations:cctxt#confirmations + ?fee + ~dry_run + ~verbose_signing + ?gas_limit + ?storage_limit + ?counter + () + >>= fun errors -> + report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + >>= function + | None -> return_unit | Some (_res, _contracts) -> return_unit) + +let unshield_cmd = + let open Client_proto_args in + let open Client_proto_context_commands in + let open Protocol.Alpha_context in + let open Client_proto_contracts in + command + ~group + ~desc:"Unshield tokens from a Sapling address to an implicit account." + (args13 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + no_print_source_flag + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg) + ( prefixes ["sapling"; "unshield"] + @@ tez_param + ~name:"qty" + ~desc:"Amount taken from shielded wallet of source." + @@ prefix "from" + @@ Sapling_key.alias_param + ~name:"src-sap" + ~desc:"Sapling account of source." + @@ prefix "to" + @@ ContractAlias.destination_param + ~name:"dst-tz" + ~desc:"Transparent destination account." + @@ prefix "using" + @@ ContractAlias.destination_param + ~name:"sapling contract" + ~desc:"Smart contract to submit this transaction to." + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + amount + (name, _sapling_uri) + (_, tz_dst) + (_contract_name, contract_dst) + cctxt -> + let open Context in + let stez = Shielded_tez.of_tez amount in + cctxt#warning + "Unshielding %a from %s to %a@ entails a loss of privacy@." + Shielded_tez.pp + stez + name + Contract.pp + tz_dst + >>= fun () -> + keys_of_implicit_account cctxt tz_dst + >>=? fun (source, src_pk, src_sk) -> + do_unshield cctxt contract_dst name stez source + >>=? fun sapling_input -> + let arg = Shielded_tez_contract_input.as_arg sapling_input in + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + Client_proto_context.transfer + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~fee_parameter + ~amount:Tez.zero + ~src_pk + ~src_sk + ~destination:contract_dst + ~source + ~arg + ?confirmations:cctxt#confirmations + ?fee + ~dry_run + ~verbose_signing + ?gas_limit + ?storage_limit + ?counter + () + >>= fun errors -> + report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + >>= function + | None -> return_unit | Some (_res, _contracts) -> return_unit) + +(* Default name for Sapling transaction file *) +let sapling_transaction_file = "sapling_transaction" + +let file_arg default_filename = + let open Clic in + arg + ~long:"file" + ~placeholder:default_filename + ~doc:"file name" + (parameter (fun _ x -> return x)) + +(** Shielded transaction are first forged and printed in a file. + Then they are submitted with the next command. **) +let forge_shielded_cmd = + let open Client_proto_args in + let open Client_proto_context_commands in + let open Client_proto_contracts in + command + ~group + ~desc:"Forge a sapling transaction and save it to a file." + (args16 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + no_print_source_flag + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg + message_arg + (file_arg sapling_transaction_file) + json_switch) + ( prefixes ["sapling"; "forge"; "transaction"] + @@ tez_param + ~name:"qty" + ~desc:"Amount taken from shielded wallet of source." + @@ prefix "from" + @@ Sapling_key.alias_param + ~name:"src-sap" + ~desc:"Sapling account of source." + @@ prefix "to" + @@ Clic.string ~name:"dst-sap" ~desc:"Sapling address of destination." + @@ prefix "using" + @@ ContractAlias.destination_param + ~name:"sapling contract" + ~desc:"Smart contract to submit this transaction to." + @@ stop ) + (fun ( _fee, + _dry_run, + _verbose_signing, + _gas_limit, + _storage_limit, + _counter, + _no_print_source, + _minimal_fees, + _minimal_nanotez_per_byte, + _minimal_nanotez_per_gas_unit, + _force_low_fee, + _fee_cap, + _burn_cap, + message, + file, + use_json_format ) + amount + (name, _sapling_uri) + destination + (_contract_name, contract_dst) + cctxt -> + let open Context in + let stez = Shielded_tez.of_tez amount in + do_sapling_transfer cctxt ?message contract_dst name stez destination + >>=? fun transaction -> + let file = Option.value ~default:sapling_transaction_file file in + cctxt#message "Writing transaction to %s@." file + >>= fun () -> + ( if use_json_format then + save_json_to_file + (Data_encoding.Json.construct UTXO.transaction_encoding transaction) + file + else + let bytes = + Hex.of_bytes + (Data_encoding.Binary.to_bytes_exn + UTXO.transaction_encoding + transaction) + in + let file = open_out_bin file in + Printf.fprintf file "0x%s" (Hex.show bytes) ; + close_out file ) ; + return_unit) + +let submit_shielded_cmd = + let open Client_proto_context_commands in + let open Client_proto_args in + let open Client_proto_contracts in + command + ~group + ~desc:"Submit a forged sapling transaction." + (args14 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + no_print_source_flag + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg + json_switch) + ( prefixes ["sapling"; "submit"] + (* TODO: Add a dedicated abstracted Clic element to parse filenames, + potentially using Sys.file_exists *) + @@ Clic.string ~name:"file" ~desc:"Filename of the forged transaction." + @@ prefix "from" + @@ ContractAlias.destination_param + ~name:"alias-tz" + ~desc:"Transparent account paying the fees." + @@ prefix "using" + @@ ContractAlias.destination_param + ~name:"sapling contract" + ~desc:"Smart contract to submit this transaction to." + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap, + use_json_format ) + filename + (_, source) + (contract_name, destination) + (cctxt : Protocol_client_context.full) -> + cctxt#message + "Reading forge transaction from file %s -- sending it to %s@." + filename + contract_name + >>= fun () -> + let open Context in + ( if use_json_format then + Lwt_utils_unix.Json.read_file filename + >>=? fun json -> + return @@ Data_encoding.Json.destruct UTXO.transaction_encoding json + else + Lwt_utils_unix.read_file filename + >>= fun hex -> + let hex = + (* remove 0x *) + String.sub hex 2 (String.length hex - 2) + in + return + @@ Data_encoding.Binary.of_bytes_exn + UTXO.transaction_encoding + Hex.(to_bytes (`Hex hex)) ) + >>=? fun transaction -> + return Shielded_tez_contract_input.(as_arg (create transaction)) + >>=? fun contract_input -> + let chain = cctxt#chain and block = cctxt#block in + keys_of_implicit_account cctxt source + >>=? fun (source, src_pk, src_sk) -> + let open Protocol.Alpha_context in + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + Client_proto_context.transfer + cctxt + ~chain + ~block + ~fee_parameter + ~amount:Tez.zero + ~src_pk + ~src_sk + ~destination + ~source + ~arg:contract_input + ?confirmations:cctxt#confirmations + ?fee + ~dry_run + ~verbose_signing + ?gas_limit + ?storage_limit + ?counter + () + >>= fun errors -> + report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + >>= function + | None -> return_unit | Some (_res, _contracts) -> return_unit) + +let for_contract_arg = + Client_proto_contracts.ContractAlias.destination_arg + ~name:"for-contract" + ~doc:"name of the contract to associate new key with" + () + +let unencrypted_switch () = + Clic.switch + ~long:"unencrypted" + ~doc:"Do not encrypt the key on-disk (for testing and debugging)." + () + +let generate_key_cmd = + command + ~group + ~desc:"Generate a new sapling key." + (args2 (Sapling_key.force_switch ()) (unencrypted_switch ())) + ( prefixes ["sapling"; "gen"; "key"] + @@ Sapling_key.fresh_alias_param @@ stop ) + (fun (force, unencrypted) name (cctxt : Protocol_client_context.full) -> + Sapling_key.of_fresh cctxt force name + >>=? fun name -> + let mnemonic = Wallet.Mnemonic.new_random in + cctxt#message + "It is important to save this mnemonic in a secure place:@\n\ + @\n\ + %a@\n\ + @\n\ + The mnemonic can be used to recover your spending key.@." + Wallet.Mnemonic.words_pp + (Bip39.to_words mnemonic) + >>= fun () -> + Wallet.register cctxt ~force ~unencrypted mnemonic name + >>=? fun _vk -> return_unit) + +let use_key_for_contract_cmd = + command + ~group + ~desc:"Use a sapling key for a contract." + (args1 memo_size_arg) + ( prefixes ["sapling"; "use"; "key"] + @@ Sapling_key.alias_param + ~name:"sapling-key" + ~desc:"Sapling key to use for the contract." + @@ prefixes ["for"; "contract"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"contract" + ~desc:"Contract the key will be used on." + @@ stop ) + (fun default_memo_size + (name, _sapling_uri) + (_contract_name, contract) + (cctxt : Protocol_client_context.full) -> + Wallet.find_vk cctxt name + >>=? fun vk -> + Context.Client_state.register + cctxt + ~default_memo_size + ~force:false + contract + vk) + +let import_key_cmd = + command + ~group + ~desc:"Restore a sapling key from mnemonic." + (args3 + (Sapling_key.force_switch ()) + (unencrypted_switch ()) + (Clic.arg + ~long:"mnemonic" + ~placeholder:"mnemonic" + ~doc:"Mnemonic as an option, only used for testing and debugging." + Client_proto_args.string_parameter)) + ( prefixes ["sapling"; "import"; "key"] + @@ Sapling_key.fresh_alias_param @@ stop ) + (fun (force, unencrypted, mnemonic_opt) + fresh_name + (cctxt : Protocol_client_context.full) -> + ( match mnemonic_opt with + | None -> + let rec loop_words (acc : string list) i = + if i > 23 then return (List.rev acc) + else + cctxt#prompt_password "Enter word %d: " i + >>=? fun word_raw -> + let word = Bytes.to_string word_raw in + match Bip39.index_of_word word with + | None -> + loop_words acc i + | Some _ -> + loop_words (word :: acc) (succ i) + in + loop_words [] 0 + | Some mnemonic -> + return (String.split_on_char ' ' mnemonic) ) + >>=? fun words -> + match Bip39.of_words words with + | None -> + failwith "Not a valid mnemonic" + | Some mnemonic -> + Sapling_key.of_fresh cctxt force fresh_name + >>=? fun name -> + Wallet.register cctxt ~force ~unencrypted mnemonic name + >>=? fun _ -> return_unit) + +let commands () = + let child_index_param = + Clic.param + ~name:"child-index" + ~desc:"Index of the child to derive." + Client_proto_args.int_parameter + in + let index_arg = + Clic.arg + ~doc:"index of the address to generate" + ~long:"address-index" + ~placeholder:"idx" + Client_proto_args.int_parameter + in + [ generate_key_cmd; + use_key_for_contract_cmd; + import_key_cmd; + command + ~group + ~desc:"Derive a key from an existing one using zip32." + (args4 + (Sapling_key.force_switch ()) + for_contract_arg + (unencrypted_switch ()) + memo_size_arg) + ( prefixes ["sapling"; "derive"; "key"] + @@ Sapling_key.fresh_alias_param @@ prefix "from" + @@ Sapling_key.alias_param + @@ prefixes ["at"; "index"] + @@ child_index_param @@ stop ) + (fun (force, contract_opt, unencrypted, default_memo_size) + fresh_name + (existing_name, _existing_uri) + child_index + (cctxt : Protocol_client_context.full) -> + Sapling_key.of_fresh cctxt force fresh_name + >>=? fun new_name -> + Wallet.derive + cctxt + ~force + ~unencrypted + existing_name + new_name + child_index + >>=? fun (path, vk) -> + cctxt#message + "Derived new key %s from %s with path %s@." + new_name + existing_name + path + >>= fun () -> + (* TODO must pass contract address for now *) + let (_, contract) = + WithExceptions.Option.get ~loc:__LOC__ contract_opt + in + Context.Client_state.register + cctxt + ~default_memo_size + ~force + contract + vk); + command + ~group + ~desc:"Generate an address for a key referenced by alias." + (args1 index_arg) + ( prefixes ["sapling"; "gen"; "address"] + @@ Sapling_key.alias_param @@ stop ) + (fun index_opt + (name, _sapling_uri) + (cctxt : Protocol_client_context.full) -> + Wallet.new_address cctxt name index_opt + >>=? fun (_, corrected_index, address) -> + let address_b58 = + Base58.simple_encode Viewing_key.address_b58check_encoding address + in + cctxt#message + "Generated address:@.%s@.at index %Ld" + address_b58 + (Viewing_key.index_to_int64 corrected_index) + >>= fun () -> return_unit); + command + ~group + ~desc:"Save a sapling viewing key in a JSON file." + no_options + ( prefixes ["sapling"; "export"; "key"] + @@ Sapling_key.alias_param @@ prefix "in" + @@ Clic.param + ~name:"file" + ~desc:"Filename." + Client_proto_args.string_parameter + @@ stop ) + (fun () (name, _sapling_uri) file (cctxt : Protocol_client_context.full) -> + Wallet.export_vk cctxt name + >>=? fun vk_json -> return (save_json_to_file vk_json file)); + command + ~group + ~desc:"Get balance associated with given sapling key and contract" + (args1 + (Clic.switch + ~doc:"Print the collection of non-spent inputs." + ~short:'v' + ~long:"verbose" + ())) + ( prefixes ["sapling"; "get"; "balance"; "for"] + @@ Sapling_key.alias_param + ~name:"sapling-key" + ~desc:"Sapling key we get balance for." + @@ prefixes ["in"; "contract"] + @@ Client_proto_contracts.ContractAlias.destination_param + ~name:"contract" + ~desc:"Contract we get balance from." + @@ stop ) + (fun verbose + (name, _sapling_uri) + (_contract_name, contract) + (cctxt : Protocol_client_context.full) -> + Wallet.find_vk cctxt name + >>= function + | Error _ -> + cctxt#error "Account %s not found" name + | Ok vk -> ( + Context.Client_state.sync_and_scan cctxt contract + >>=? fun contract_state -> + Context.Contract_state.find_account vk contract_state + |> function + | None -> + cctxt#error "Account %s not found" name + | Some account -> + ( if verbose then + cctxt#answer + "@[Received Sapling transactions for %s@,@[%a@]@]" + name + Context.Account.pp_unspent + account + else Lwt.return_unit ) + >>= fun () -> + cctxt#answer + "Total Sapling funds %a%s" + Context.Shielded_tez.pp + (Context.Account.balance account) + Client_proto_args.tez_sym + >>= fun () -> return_unit )); + command + ~group + ~desc:"List sapling keys." + no_options + (fixed ["sapling"; "list"; "keys"]) + (fun () (cctxt : Protocol_client_context.full) -> + Sapling_key.load cctxt + >>=? fun l -> + List.iter_s + (fun (s, _) -> cctxt#message "%s" s) + (List.sort (fun (s1, _) (s2, _) -> String.compare s1 s2) l) + >>= fun () -> return_unit); + shield_cmd; + unshield_cmd; + forge_shielded_cmd; + submit_shielded_cmd ] diff --git a/src/proto_009_PsFLoren/lib_client_sapling/client_sapling_commands.mli b/src/proto_009_PsFLoren/lib_client_sapling/client_sapling_commands.mli new file mode 100644 index 0000000000000000000000000000000000000000..769a4eac58e9861f43d8e6141c94695969a2887d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/client_sapling_commands.mli @@ -0,0 +1,23 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +val commands : unit -> Protocol_client_context.full Clic.command list diff --git a/src/proto_009_PsFLoren/lib_client_sapling/context.ml b/src/proto_009_PsFLoren/lib_client_sapling/context.ml new file mode 100644 index 0000000000000000000000000000000000000000..78bdac3959f5c3b7afcf93af59929e7c1374c4ef --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/context.ml @@ -0,0 +1,576 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +open Tezos_sapling.Core.Client + +let _ = Random.self_init () + +module Tez = Protocol.Alpha_context.Tez + +module Shielded_tez : sig + type t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val zero : t + + val of_mutez : int64 -> t option + + val to_mutez : t -> int64 + + val of_tez : Tez.t -> t + + val ( +? ) : t -> t -> t tzresult + + val ( -? ) : t -> t -> t tzresult +end = struct + include Tez + + let ( +? ) a b = a +? b |> Environment.wrap_tzresult + + let ( -? ) a b = a -? b |> Environment.wrap_tzresult + + let of_tez t = + let i = Tez.to_mutez t in + assert (UTXO.valid_amount i) ; + WithExceptions.Option.get ~loc:__LOC__ @@ of_mutez i +end + +module Shielded_tez_contract_input = struct + type t = UTXO.transaction * Signature.public_key_hash option + + let create ?pkh tr = (tr, pkh) + + let encoding = + let open Data_encoding in + obj2 + (req "transaction" UTXO.transaction_encoding) + (opt "pkh" Signature.Public_key_hash.encoding) + + let pp ppf t = + let open Data_encoding in + let json = Json.construct encoding t in + Json.pp ppf json + + let michelson (tr, pkopt) = + let open Tezos_micheline in + let open Protocol.Alpha_context in + let a = + Micheline.Bytes + (0, Data_encoding.Binary.to_bytes_exn UTXO.transaction_encoding tr) + in + let b = + match pkopt with + | None -> + Micheline.Prim (0, Script.D_None, [], []) + | Some v -> + let value = + Micheline.Bytes + ( 0, + Data_encoding.Binary.to_bytes_exn + Signature.Public_key_hash.encoding + v ) + in + Micheline.Prim (0, Script.D_Some, [value], []) + in + Micheline.strip_locations + @@ Micheline.Seq (0, [Micheline.Prim (0, Script.D_Pair, [a; b], [])]) + + let pp_michelson ppf t = + let value = michelson t in + Michelson_v1_printer.print_expr ppf value + + let as_arg t = Format.asprintf "%a" pp_michelson t +end + +(** The inputs and outputs are shuffled to prevent meta-data analysis. **) +module Shuffle = struct + let list l = + let a = Array.of_list l in + let len = Array.length a in + for i = len downto 2 do + let idx = Random.int i in + let swp_idx = i - 1 in + let tmp = a.(swp_idx) in + a.(swp_idx) <- a.(idx) ; + a.(idx) <- tmp + done ; + Array.to_list a + + let pair x y = if Random.bool () then [y; x] else [x; y] +end + +type error += Balance_too_low of Shielded_tez.t * Shielded_tez.t + +let register_error_kind category ~id ~title ~description ?pp encoding + from_error to_error = + let id = "client_sapling." ^ Protocol.name ^ "." ^ id in + register_error_kind + category + ~id + ~title + ~description + ?pp + encoding + from_error + to_error + +let () = + register_error_kind + `Temporary + ~id:"balance_too_low" + ~title:"Balance too low" + ~description:"The sender contract does not have enough tokens." + ~pp:(fun ppf (balance, amount) -> + Format.fprintf + ppf + "@[Balance too low (%a) to spend %a@]" + Shielded_tez.pp + balance + Shielded_tez.pp + amount) + Data_encoding.( + obj2 + (req "actual_balance" Shielded_tez.encoding) + (req "amount" Shielded_tez.encoding)) + (function + | Balance_too_low (balance, amount) -> Some (balance, amount) | _ -> None) + (fun (balance, amount) -> Balance_too_low (balance, amount)) + +module Storage = Tezos_sapling.Storage +module F = Tezos_sapling.Forge + +module Input_set = struct + include Set.Make (F.Input) + + let to_list = elements + + let pp_f pp i = + Format.fprintf + pp + "@[%s %Ld@]" + (Base58.simple_encode + Viewing_key.address_b58check_encoding + (F.Input.address i)) + (F.Input.amount i) +end + +module Account = struct + type t = { + vk : Viewing_key.t; + unspents : Input_set.t; + balance : Shielded_tez.t; + } + + let encoding = + let open Data_encoding in + conv + (fun cs -> (cs.vk, Input_set.to_list cs.unspents, cs.balance)) + (fun (vk, unspents, balance) -> + {vk; unspents = Input_set.of_list unspents; balance}) + (obj3 + (req "vk" Viewing_key.encoding) + (req "unspents" (list F.Input.encoding)) + (req "balance" Shielded_tez.encoding)) + + let create vk = {vk; unspents = Input_set.empty; balance = Shielded_tez.zero} + + let balance c = c.balance + + let add_unspent c input = + let amount = + WithExceptions.Option.get ~loc:__LOC__ + @@ Shielded_tez.of_mutez (F.Input.amount input) + in + match Shielded_tez.(c.balance +? amount) with + | Error _ -> + assert false (* overflow *) + | Ok balance -> + let unspents = Input_set.add input c.unspents in + {c with balance; unspents} + + let remove_unspent c input = + let amount = + WithExceptions.Option.get ~loc:__LOC__ + @@ Shielded_tez.of_mutez (F.Input.amount input) + in + match Shielded_tez.(c.balance -? amount) with + | Error _ -> + assert false (* negative balance *) + | Ok balance -> + let unspents = Input_set.remove input c.unspents in + {c with balance; unspents} + + let filter_spent account storage = + Input_set.fold + (fun input acc -> + if F.Input.is_spent input storage account.vk then + remove_unspent acc input + else acc) + account.unspents + account + + let pick_input c = + let ( >?| ) x f = Option.map f x in + Input_set.choose c.unspents + >?| fun unspent -> + let c = remove_unspent c unspent in + (unspent, c) + + let pp_unspent : Format.formatter -> t -> unit = + fun ppf a -> + (Format.pp_print_list ~pp_sep:Format.pp_print_cut Input_set.pp_f ppf) + (Input_set.elements a.unspents) +end + +module Contract_state = struct + module Accounts = struct + include Set.Make (struct + type t = Account.t + + let compare a b = + let open Account in + Bytes.compare (Viewing_key.to_bytes a.vk) (Viewing_key.to_bytes b.vk) + end) + + let replace a set = add a (remove a set) + + let find vk accounts = find (Account.create vk) accounts + end + + let accounts_encoding = + let open Data_encoding in + conv + Accounts.elements + (List.fold_left (fun m e -> Accounts.add e m) Accounts.empty) + (list Account.encoding) + + type t = {accounts : Accounts.t; storage : Storage.state} + + let encoding = + let open Data_encoding in + conv + (fun t -> (t.accounts, t.storage)) + (fun (accounts, storage) -> {accounts; storage}) + (obj2 + (req "accounts" accounts_encoding) + (req "storage" Storage.state_encoding)) + + let empty ~memo_size = + {accounts = Accounts.empty; storage = Storage.empty ~memo_size} + + let find_account vk contract_state = Accounts.find vk contract_state.accounts + + let init ~force vk state = + Accounts.find vk state.accounts + |> function + | None -> + let accounts = Accounts.add (Account.create vk) state.accounts in + return {state with accounts} + | Some _ -> + if force then + let accounts = Accounts.add (Account.create vk) state.accounts in + return {state with accounts} + else failwith "vk already present" + + let add_unspent vk input accounts = + let account = + Accounts.find vk accounts |> WithExceptions.Option.get ~loc:__LOC__ + in + let account = Account.add_unspent account input in + Accounts.replace account accounts + + (** Scan the Sapling storage of a smart contract and update the accounts of + all known viewing keys for that contract *) + let scan state storage = + (* remove newly spent inputs *) + let accounts = + Accounts.map + (fun account -> Account.filter_spent account storage) + state.accounts + in + (* get all the vks that need to be scanned for *) + let vks = + Accounts.fold + (fun account acc -> Account.(account.vk) :: acc) + accounts + [] + in + let (size, _) = Storage.size storage in + let rec aux pos accounts = + if pos < size then + (* try to decrypt each inputs with all vks *) + List.fold_left + (fun acc vk -> + match F.Input.get storage pos vk with + | None -> + acc + | Some input -> + (vk, input) :: acc) + [] + vks + |> function + | [] -> + aux (Int64.succ pos) accounts + | [(vk, (_message, forge_input))] -> + let is_spent = F.Input.is_spent forge_input storage vk in + if is_spent then aux (Int64.succ pos) accounts + else aux (Int64.succ pos) (add_unspent vk forge_input accounts) + | _ -> + assert false (* got more than one decrypting key *) + else accounts + in + let (current_size, _) = Storage.size state.storage in + let accounts = aux current_size accounts in + {accounts; storage} + + (** Update the Sapling storage of a smart contract using a diff, checking that + the resulting Merkle tree has a root equal to the one in the diff. *) + let update_storage contract_state (root, diff) = + let open Protocol.Alpha_context.Sapling in + let storage = + Tezos_sapling.Storage.add + contract_state.storage + diff.commitments_and_ciphertexts + in + let computed_root = Storage.get_root storage in + if computed_root <> root then + Stdlib.failwith "Commitment tree inconsistent wrt to node." + else + let storage = + List.fold_left + (fun s nf -> Storage.add_nullifier s nf) + storage + diff.nullifiers + in + scan contract_state storage +end + +module Client_state = struct + module Map = Map.Make (Protocol.Alpha_context.Contract) + + type t = Contract_state.t Map.t + + let encoding = + let open Data_encoding in + conv + Map.bindings + (List.fold_left (fun m (k, v) -> Map.add k v m) Map.empty) + (list + (obj2 + (req "contract" Protocol.Alpha_context.Contract.encoding) + (req "state" Contract_state.encoding))) + + let filename = "sapling_state" + + let load (cctxt : #Client_context.wallet) = + cctxt#load filename ~default:Map.empty encoding + + let write (cctxt : #Client_context.wallet) t = + cctxt#write filename t encoding + + let get_or_init ~default_memo_size contract client_state = + Map.find contract client_state + |> function + | None -> ( + match default_memo_size with + | None -> + failwith + "Unknown memo size for contract %s and none was provided in options" + @@ Protocol.Alpha_context.Contract.to_b58check contract + | Some memo_size -> + let contract_state = Contract_state.empty ~memo_size in + let client_state = Map.add contract contract_state client_state in + return (contract_state, client_state) ) + | Some contract_state -> + return (contract_state, client_state) + + let register cctxt ~force ~default_memo_size contract vk = + load cctxt + >>=? fun client_state -> + get_or_init ~default_memo_size contract client_state + >>=? fun (contract_state, client_state) -> + Contract_state.init ~force vk contract_state + >>=? fun contract_state -> + let client_state = Map.add contract contract_state client_state in + write cctxt client_state + + let find (cctxt : #Client_context.full) contract state = + Map.find contract state + |> function + | None -> + cctxt#error + "Contract %s not found" + (Protocol.Alpha_context.Contract.to_b58check contract) + | Some v -> + return v + + (** Call the node RPC to obtain the storage diff of a contract *) + let get_diff cctxt contract offset_commitment offset_nullifier = + Protocol.Alpha_services.Contract.single_sapling_get_diff + cctxt + (cctxt#chain, cctxt#block) + contract + ~offset_commitment + ~offset_nullifier + () + + let sync_and_scan cctxt contract = + load cctxt + >>=? fun state -> + find cctxt contract state + >>=? fun contract_state -> + let (cm_pos, nf_pos) = Storage.size contract_state.storage in + get_diff cctxt contract cm_pos nf_pos + >>=? fun diff -> + let contract_state = Contract_state.update_storage contract_state diff in + let state = Map.add contract contract_state state in + write cctxt state >>=? fun () -> return contract_state +end + +(** Truncate or pad the message to fit the memo_size *) +let adjust_message_length (cctxt : #Client_context.full) ?message memo_size = + match message with + | None -> + cctxt#warning + "no message provided, adding a zeroes filled message of the required \ + length: %d " + memo_size + >|= fun () -> Bytes.make memo_size '\000' + | Some message -> + let message_length = Bytes.length message in + if message_length = memo_size then Lwt.return message + else if message_length > memo_size then + cctxt#warning + "Your message is too long (%d bytes) and will therefore be \ + truncated to %d bytes" + message_length + memo_size + >|= fun () -> Bytes.sub message 0 memo_size + else + cctxt#warning + "Your message is too short (%d bytes) and will therefore be \ + right-padded with zero bytes to reach a %d-byte length" + message_length + memo_size + >|= fun () -> + Bytes.cat message (Bytes.make (memo_size - message_length) '\000') + +let create_payment ~message dst amount = + let amount = Shielded_tez.to_mutez amount in + F.make_output dst amount message + +(** Return a list of inputs belonging to an account sufficient to cover an + amount, together with the change remaining. *) +let get_shielded_amount amount account = + let balance = Account.balance account in + error_unless (balance >= amount) (Balance_too_low (balance, amount)) + >|? fun () -> + let to_pay = Shielded_tez.to_mutez amount in + let inputs_to_spend = [] in + let rec loop to_pay chosen_inputs account = + if Int64.(compare to_pay zero) > 0 then + Account.pick_input account + |> function + | None -> + Stdlib.failwith "Not enough inputs" (* TODO raise a proper error *) + | Some (next_in, account) -> + let next_val = F.Input.amount next_in in + let rest_to_pay = Int64.sub to_pay next_val in + loop rest_to_pay (next_in :: chosen_inputs) account + else + let change = + WithExceptions.Option.get ~loc:__LOC__ + @@ Shielded_tez.of_mutez @@ Int64.abs to_pay + in + (chosen_inputs, change) + in + loop to_pay inputs_to_spend account + +let create_payback ~memo_size address amount = + let plaintext_message = Bytes.make memo_size '\000' in + let amount = Shielded_tez.to_mutez amount in + F.make_output address amount plaintext_message + +(* The caller should check that the account exists already *) +let unshield ~src ~dst ~backdst amount (state : Contract_state.t) anti_replay = + let vk = Viewing_key.of_sk src in + let account = + Contract_state.find_account vk state + |> WithExceptions.Option.get ~loc:__LOC__ + in + get_shielded_amount amount account + >|? fun (inputs, change) -> + let memo_size = Storage.get_memo_size state.storage in + let payback = create_payback ~memo_size backdst change in + let sapling_transaction = + F.forge_transaction + (Shuffle.list inputs) + [payback] + src + anti_replay + state.storage + in + Shielded_tez_contract_input.create ~pkh:dst sapling_transaction + +let shield cctxt ~dst ?message amount (state : Contract_state.t) anti_replay = + let shielded_amount = Shielded_tez.of_tez amount in + let memo_size = Storage.get_memo_size Contract_state.(state.storage) in + adjust_message_length cctxt ?message memo_size + >>= fun message -> + let payment = create_payment ~message dst shielded_amount in + let negative_amount = Int64.neg (Tez.to_mutez amount) in + let sapling_transaction = + F.forge_shield_transaction + [payment] + negative_amount + anti_replay + Contract_state.(state.storage) + in + return (Shielded_tez_contract_input.create sapling_transaction) + +(* The caller should check that the account exists already *) +let transfer cctxt ~src ~dst ~backdst ?message amount + (state : Contract_state.t) anti_replay = + let vk = Viewing_key.of_sk src in + let account = + Contract_state.find_account vk state + |> WithExceptions.Option.get ~loc:__LOC__ + in + let memo_size = Storage.get_memo_size state.storage in + adjust_message_length cctxt ?message memo_size + >|= fun message -> + get_shielded_amount amount account + >|? fun (inputs, change) -> + let payment = create_payment ~message dst amount in + let payback = create_payback ~memo_size backdst change in + let sapling_transaction = + F.forge_transaction + (Shuffle.list inputs) + (Shuffle.pair payback payment) + src + anti_replay + state.storage + in + sapling_transaction diff --git a/src/proto_009_PsFLoren/lib_client_sapling/context.mli b/src/proto_009_PsFLoren/lib_client_sapling/context.mli new file mode 100644 index 0000000000000000000000000000000000000000..72963733eb7c0732c740bb32c0790015fe5f2276 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/context.mli @@ -0,0 +1,157 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +(** + This module allows the creation Sapling transactions: shield, unshield and + transfer. + Because Sapling uses an UTXO model, it is necessary for the client to + maintain locally the set of unspent outputs for each viewing key, for each + smart contract. This operation is called scanning. + This local cache is updated downloading from the node only the difference + from the last scanned state. +*) + +open Tezos_sapling.Core.Client + +module Tez : module type of Protocol.Alpha_context.Tez + +(** This module is used to represent any shielded token to avoid confusing it + with Tez. *) +module Shielded_tez : sig + type t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val zero : t + + val of_mutez : int64 -> t option + + val to_mutez : t -> int64 + + val of_tez : Tez.t -> t + + val ( +? ) : t -> t -> t tzresult +end + +(** Actual input to a smart contract handling Sapling transactions *) +module Shielded_tez_contract_input : sig + type t + + val create : ?pkh:Signature.Public_key_hash.t -> UTXO.transaction -> t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val as_arg : t -> string +end + +(** Account corresponding to a contract and a viewing key *) +module Account : sig + type t + + val balance : t -> Shielded_tez.t + + val pp_unspent : Format.formatter -> t -> unit +end + +(** State of a contract, potentially involving several viewing keys *) +module Contract_state : sig + type t + + val find_account : Viewing_key.t -> t -> Account.t option +end + +module Client_state : sig + type t + + val find : + Protocol_client_context.full -> + Protocol.Alpha_context.Contract.t -> + t -> + Contract_state.t tzresult Lwt.t + + val register : + Protocol_client_context.full -> + force:bool -> + default_memo_size:int option -> + Protocol.Alpha_context.Contract.t -> + Viewing_key.t -> + unit tzresult Lwt.t + + (** Synchronise our local state with the blockchain's. + The state must be recent enough to craft correct transactions. + The limit enforced by the protocol if 120 blocks. + Also scans, ie. checks for incoming payments and add + them to our balance. + **) + val sync_and_scan : + Protocol_client_context.full -> + Protocol.Alpha_context.Contract.t -> + Contract_state.t tzresult Lwt.t +end + +(** [shield ~message ~dst tez cstate anti-replay] returns a transaction + shielding [tez] tez to a sapling address [dst] using a sapling + storage [cstate] and the anti-replay string. *) +val shield : + #Client_context.full -> + dst:Viewing_key.address -> + ?message:bytes -> + Tez.t -> + Contract_state.t -> + string -> + Shielded_tez_contract_input.t tzresult Lwt.t + +(** [unshield ~src_name ~src ~dst ~backdst stez cstate storage] returns + a transaction unshielding [stez] shielded tokens from a sapling wallet + [src] to a transparent tezos address [dst], sending the change back to + [backdst] and using a Sapling storage [cstate] and a anti-replay string. + The transaction is refused if there is an insufficient amount of shielded + tez in the wallet [src], the error is raised with [src_name]. + *) +val unshield : + src:Spending_key.t -> + dst:Signature.public_key_hash -> + backdst:Viewing_key.address -> + Shielded_tez.t -> + Contract_state.t -> + string -> + Shielded_tez_contract_input.t tzresult + +(** [transfer ~message ~src ~dst ~backdst amount cstate anti-replay] creates a + Sapling transaction of [amount] shielded tez from Sapling wallet [src] to + Sapling address [dst], sending the change to [backdst], using a Sapling + storage [cstate] and a anti-replay string. + [~message] is a message that will be uploaded encrypted on chain. *) +val transfer : + #Client_context.full -> + src:Spending_key.t -> + dst:Viewing_key.address -> + backdst:Viewing_key.address -> + ?message:bytes -> + Shielded_tez.t -> + Contract_state.t -> + string -> + UTXO.transaction tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_client_sapling/dune b/src/proto_009_PsFLoren/lib_client_sapling/dune new file mode 100644 index 0000000000000000000000000000000000000000..9992d82d23a916d21483940d3b8db22eb1d63f86 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/dune @@ -0,0 +1,23 @@ +(library + (name tezos_client_sapling_009_PsFLoren) + (public_name tezos-client-sapling-009-PsFLoren) + (libraries tezos-base + tezos-crypto + tezos-client-base + tezos-signer-backends + tezos-client-009-PsFLoren + tezos-client-009-PsFLoren-commands + tezos-protocol-009-PsFLoren) + (library_flags (:standard -linkall)) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_stdlib_unix + -open Tezos_client_base + -open Tezos_client_009_PsFLoren + -open Tezos_client_009_PsFLoren_commands + -open Tezos_protocol_009_PsFLoren + -open Tezos_protocol_environment_009_PsFLoren))) + +(alias + (name runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/lib_client_sapling/dune-project b/src/proto_009_PsFLoren/lib_client_sapling/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..bb1284159c48900f39ffc759e520f68ab1297169 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/dune-project @@ -0,0 +1,2 @@ +(lang dune 1.11) +(name tezos-client-sapling) diff --git a/src/proto_009_PsFLoren/lib_client_sapling/tezos-client-sapling-009-PsFLoren.opam b/src/proto_009_PsFLoren/lib_client_sapling/tezos-client-sapling-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..e16bf81862ad931ef83ab442f10e3aa06361ecd0 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/tezos-client-sapling-009-PsFLoren.opam @@ -0,0 +1,25 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "ocamlfind" { build } + "dune" { >= "1.7" } + "tezos-base" + "tezos-clic" + "tezos-crypto" + "tezos-client-base" + "tezos-signer-backends" + "tezos-client-009-PsFLoren" + "tezos-client-009-PsFLoren-commands" + "tezos-protocol-009-PsFLoren" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos: sapling support for `tezos-client`" diff --git a/src/proto_009_PsFLoren/lib_client_sapling/wallet.ml b/src/proto_009_PsFLoren/lib_client_sapling/wallet.ml new file mode 100644 index 0000000000000000000000000000000000000000..df6295ec16b7490a847c28838a2372f4aa3e2aa0 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/wallet.ml @@ -0,0 +1,134 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +open Client_keys +open Tezos_sapling.Core.Client + +module Mnemonic = struct + let new_random = Bip39.of_entropy (Hacl.Rand.gen 32) + + let to_sapling_key mnemonic = + (* Z-cash needs 32 bytes and BIP-39 gives 64 bytes of entropy. + We xor the two halves in case the entropy is not well distributed. *) + let seed_64_to_seed_32 (seed_64 : bytes) : bytes = + assert (Bytes.length seed_64 = 64) ; + let first_32 = Bytes.sub seed_64 0 32 in + let second_32 = Bytes.sub seed_64 32 32 in + let seed_32 = Bytes.create 32 in + for i = 0 to 31 do + Bytes.set + seed_32 + i + (Char.chr + ( Char.code (Bytes.get first_32 i) + lxor Char.code (Bytes.get second_32 i) )) + done ; + seed_32 + in + Spending_key.of_seed (seed_64_to_seed_32 (Bip39.to_seed mnemonic)) + + let words_pp = Format.(pp_print_list ~pp_sep:pp_print_space pp_print_string) +end + +(* Transform a spending key to an uri, encrypted or not. *) +let to_uri unencrypted cctxt sapling_key = + if unencrypted then + return (Tezos_signer_backends.Unencrypted.make_sapling_key sapling_key) + else Tezos_signer_backends.Encrypted.encrypt_sapling_key cctxt sapling_key + +(** Transform an uri into a spending key, asking for a password if the uri was + encrypted. *) +let from_uri (cctxt : #Client_context.full) uri = + Tezos_signer_backends.Encrypted.decrypt_sapling_key cctxt uri + +let register (cctxt : #Client_context.full) ?(force = false) + ?(unencrypted = false) mnemonic name = + let sk = Mnemonic.to_sapling_key mnemonic in + to_uri unencrypted cctxt sk + >>=? fun sk_uri -> + let key = + { + sk = sk_uri; + path = [Spending_key.child_index sk]; + address_index = Viewing_key.default_index; + } + in + Sapling_key.add ~force cctxt name key + >>=? fun () -> return @@ Viewing_key.of_sk sk + +let derive (cctxt : #Client_context.full) ?(force = false) + ?(unencrypted = false) src_name dst_name child_index = + Sapling_key.find cctxt src_name + >>=? fun k -> + from_uri cctxt k.sk + >>=? fun src_sk -> + let child_index = Int32.of_int child_index in + let dst_sk = Spending_key.derive_key src_sk child_index in + to_uri unencrypted cctxt dst_sk + >>=? fun dst_sk_uri -> + let dst_key = + { + sk = dst_sk_uri; + path = child_index :: k.path; + address_index = Viewing_key.default_index; + } + in + (* TODO check this force *) + let _ = force in + Sapling_key.add ~force:true cctxt dst_name dst_key + >>=? fun () -> + let path = + String.concat "/" (List.map Int32.to_string (List.rev dst_key.path)) + in + return (path, Viewing_key.of_sk dst_sk) + +let find_vk cctxt name = + Sapling_key.find cctxt name + >>=? fun k -> + from_uri cctxt k.sk >>=? fun sk -> return (Viewing_key.of_sk sk) + +let new_address (cctxt : #Client_context.full) name index_opt = + Sapling_key.find cctxt name + >>=? fun k -> + let index = + match index_opt with + | None -> + k.address_index + | Some i -> + Viewing_key.index_of_int64 (Int64.of_int i) + in + from_uri cctxt k.sk + >>=? fun sk -> + return (Viewing_key.of_sk sk) + >>=? fun vk -> + (* Viewing_key.new_address finds the smallest index greater or equal to + [index] that generates a correct address. *) + let (corrected_index, address) = Viewing_key.new_address vk index in + Sapling_key.update + cctxt + name + {k with address_index = Viewing_key.index_succ corrected_index} + >>=? fun () -> return (sk, corrected_index, address) + +let export_vk cctxt name = + find_vk cctxt name + >>=? fun vk -> return (Data_encoding.Json.construct Viewing_key.encoding vk) diff --git a/src/proto_009_PsFLoren/lib_client_sapling/wallet.mli b/src/proto_009_PsFLoren/lib_client_sapling/wallet.mli new file mode 100644 index 0000000000000000000000000000000000000000..17e0e59d0af4acfdd6d415ed53c2f593d357d9b8 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_client_sapling/wallet.mli @@ -0,0 +1,75 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +open Tezos_sapling.Core.Client + +(** Mnemonic of 24 common english words from which a key can be derived. + The mnemonic follows the BIP-39 spec. *) +module Mnemonic : sig + val new_random : Bip39.t + + (** Pretty printer for printing a list of words of a mnemonic. *) + val words_pp : Format.formatter -> string list -> unit +end + +(** Add to the wallet a new spending key derived from a mnemonic and identified + by an alias. The wallet is updated and the corresponding viewing key is + returned. + If [force] it will overwrite an existing alias. *) +val register : + #Client_context.full -> + ?force:bool -> + ?unencrypted:bool -> + Bip39.t -> + string -> + Viewing_key.t tzresult Lwt.t + +(** [derive parent child index] derives a key with alias [child] from an + existing key with alias [parent] at [index] using ZIP32. + If a new index is required the state of the wallet is updated. + The path and viewing key corresponding to the generated key are returned. *) +val derive : + #Client_context.full -> + ?force:bool -> + ?unencrypted:bool -> + string -> + string -> + int -> + (string * Viewing_key.t) tzresult Lwt.t + +val find_vk : #Client_context.full -> string -> Viewing_key.t tzresult Lwt.t + +(** Generate a new address. + If an optional index is provided, try to derive the address at this index, + otherwise use the first viable one. + Not all indexes correspond to a valid address so successive ones are tried. + Once a valid index is found it is recorded in the wallet. + Return also the corresponding sk and vk to avoid asking the user multiple + times for the description password. *) +val new_address : + #Client_context.full -> + string -> + int option -> + (Spending_key.t * Viewing_key.index * Viewing_key.address) tzresult Lwt.t + +val export_vk : + #Client_context.full -> string -> Data_encoding.Json.json tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/.ocamlformat b/src/proto_009_PsFLoren/lib_delegate/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_blocks.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_blocks.ml new file mode 100644 index 0000000000000000000000000000000000000000..e9dabfa81c708f8189bda857ac97badbfbe4c2a0 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_blocks.ml @@ -0,0 +1,210 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type block_info = { + hash : Block_hash.t; + chain_id : Chain_id.t; + predecessor : Block_hash.t; + fitness : Bytes.t list; + timestamp : Time.Protocol.t; + protocol : Protocol_hash.t; + next_protocol : Protocol_hash.t; + proto_level : int; + level : Raw_level.t; + context : Context_hash.t; + predecessor_block_metadata_hash : Block_metadata_hash.t option; + predecessor_operations_metadata_hash : + Operation_metadata_list_list_hash.t option; +} + +let raw_info cctxt ?(chain = `Main) hash shell_header = + let block = `Hash (hash, 0) in + Shell_services.Chain.chain_id cctxt ~chain () + >>=? fun chain_id -> + Shell_services.Blocks.protocols cctxt ~chain ~block () + >>=? fun {current_protocol = protocol; next_protocol} -> + Shell_services.Blocks.metadata_hash cctxt ~chain ~block () + >>= (function + | Ok predecessor_block_metadata_hash -> + return_some predecessor_block_metadata_hash + | Error _ -> + return_none) + >>=? fun predecessor_block_metadata_hash -> + Shell_services.Blocks.Operation_metadata_hashes.root cctxt ~chain ~block () + >>= (function + | Ok predecessor_operations_metadata_hash -> + return_some predecessor_operations_metadata_hash + | Error _ -> + return_none) + >>=? fun predecessor_operations_metadata_hash -> + let { Tezos_base.Block_header.predecessor; + fitness; + timestamp; + level; + context; + proto_level; + _ } = + shell_header + in + match Raw_level.of_int32 level with + | Ok level -> + return + { + hash; + chain_id; + predecessor; + fitness; + timestamp; + protocol; + next_protocol; + proto_level; + level; + context; + predecessor_block_metadata_hash; + predecessor_operations_metadata_hash; + } + | Error _ -> + failwith "Cannot convert level into int32" + +let info cctxt ?(chain = `Main) block = + Shell_services.Blocks.hash cctxt ~chain ~block () + >>=? fun hash -> + Shell_services.Blocks.Header.shell_header cctxt ~chain ~block () + >>=? fun shell_header -> raw_info cctxt ~chain hash shell_header + +module Block_seen_event = struct + type t = { + hash : Block_hash.t; + header : Tezos_base.Block_header.t; + occurrence : [`Valid_blocks of Chain_id.t | `Heads]; + } + + let make hash header occurrence () = {hash; header; occurrence} + + module Definition = struct + let name = "block-seen-" ^ Protocol.name + + type nonrec t = t + + let encoding = + let open Data_encoding in + let v0_encoding = + conv + (function {hash; header; occurrence} -> (hash, occurrence, header)) + (fun (b, o, h) -> make b h o ()) + (obj3 + (req "hash" Block_hash.encoding) + (* Occurrence has to come before header, because: + (Invalid_argument + "Cannot merge two objects when the left element is of + variable length and the right one of dynamic + length. You should use the reverse order, or wrap the + second one with Data_encoding.dynamic_size.") *) + (req + "occurrence" + (union + [ case + ~title:"heads" + (Tag 0) + (obj1 (req "occurrence-kind" (constant "heads"))) + (function `Heads -> Some () | _ -> None) + (fun () -> `Heads); + case + ~title:"valid-blocks" + (Tag 1) + (obj2 + (req "occurrence-kind" (constant "valid-blocks")) + (req "chain-id" Chain_id.encoding)) + (function + | `Valid_blocks ch -> Some ((), ch) | _ -> None) + (fun ((), ch) -> `Valid_blocks ch) ])) + (req "header" Tezos_base.Block_header.encoding)) + in + With_version.(encoding ~name (first_version v0_encoding)) + + let pp ~short:_ ppf {hash; _} = + Format.fprintf ppf "Saw block %a" Block_hash.pp_short hash + + let doc = "Block observed while monitoring a blockchain." + + let level _ = Internal_event.Info + end + + module Event = Internal_event.Make (Definition) +end + +let monitor_valid_blocks cctxt ?chains ?protocols ~next_protocols () = + Monitor_services.valid_blocks cctxt ?chains ?protocols ?next_protocols () + >>=? fun (block_stream, _stop) -> + return + (Lwt_stream.map_s + (fun ((chain, block), header) -> + Block_seen_event.( + Event.emit (make block header (`Valid_blocks chain))) + >>=? fun () -> + raw_info + cctxt + ~chain:(`Hash chain) + block + header.Tezos_base.Block_header.shell) + block_stream) + +let monitor_heads cctxt ~next_protocols chain = + Monitor_services.heads cctxt ?next_protocols chain + >>=? fun (block_stream, _stop) -> + return + (Lwt_stream.map_s + (fun (block, ({Tezos_base.Block_header.shell; _} as header)) -> + Block_seen_event.(Event.emit (make block header `Heads)) + >>=? fun () -> raw_info cctxt ~chain block shell) + block_stream) + +let blocks_from_current_cycle cctxt ?(chain = `Main) block ?(offset = 0l) () = + Shell_services.Blocks.hash cctxt ~chain ~block () + >>=? fun hash -> + Shell_services.Blocks.Header.shell_header cctxt ~chain ~block () + >>=? fun {level; _} -> + Alpha_services.Helpers.levels_in_current_cycle cctxt ~offset (chain, block) + >>= function + | Error (RPC_context.Not_found _ :: _) -> + return_nil + | Error _ as err -> + Lwt.return err + | Ok (first, last) -> ( + let length = Int32.to_int (Int32.sub level (Raw_level.to_int32 first)) in + Shell_services.Blocks.list cctxt ~chain ~heads:[hash] ~length () + >>=? function + | [] -> + return_nil + | hd :: _ -> + let blocks = + List.remove (length - Int32.to_int (Raw_level.diff last first)) hd + in + if Int32.equal level (Raw_level.to_int32 last) then + return (hash :: blocks) + else return blocks ) diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_blocks.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_blocks.mli new file mode 100644 index 0000000000000000000000000000000000000000..4167be75ce1b8aa531508e8c02c1dbe355c439f7 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_blocks.mli @@ -0,0 +1,71 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type block_info = { + hash : Block_hash.t; + chain_id : Chain_id.t; + predecessor : Block_hash.t; + fitness : Bytes.t list; + timestamp : Time.Protocol.t; + protocol : Protocol_hash.t; + next_protocol : Protocol_hash.t; + proto_level : int; + level : Raw_level.t; + context : Context_hash.t; + predecessor_block_metadata_hash : Block_metadata_hash.t option; + predecessor_operations_metadata_hash : + Operation_metadata_list_list_hash.t option; +} + +val info : + #Protocol_client_context.rpc_context -> + ?chain:Chain_services.chain -> + Block_services.block -> + block_info tzresult Lwt.t + +val monitor_valid_blocks : + #Protocol_client_context.rpc_context -> + ?chains:Chain_services.chain list -> + ?protocols:Protocol_hash.t list -> + next_protocols:Protocol_hash.t list option -> + unit -> + block_info tzresult Lwt_stream.t tzresult Lwt.t + +val monitor_heads : + #Protocol_client_context.rpc_context -> + next_protocols:Protocol_hash.t list option -> + Chain_services.chain -> + block_info tzresult Lwt_stream.t tzresult Lwt.t + +val blocks_from_current_cycle : + #Protocol_client_context.rpc_context -> + ?chain:Chain_services.chain -> + Block_services.block -> + ?offset:int32 -> + unit -> + Block_hash.t list tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_denunciation.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_denunciation.ml new file mode 100644 index 0000000000000000000000000000000000000000..2a0f8068b334029c27d502d495ac1903e047b66c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_denunciation.ml @@ -0,0 +1,399 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Internal_event.Legacy_logging.Make_semantic (struct + let name = Protocol.name ^ ".baking.denunciation" +end) + +open Protocol +open Alpha_context +open Protocol_client_context +open Client_baking_blocks +open Logging + +module HLevel = Hashtbl.Make (struct + type t = Chain_id.t * Raw_level.t + + let equal (c, l) (c', l') = Chain_id.equal c c' && Raw_level.equal l l' + + let hash (c, lvl) = Hashtbl.hash (c, lvl) +end) + +module Delegate_Map = Map.Make (Signature.Public_key_hash) + +type state = { + (* Endorsements seen so far *) + endorsements_table : Kind.endorsement operation Delegate_Map.t HLevel.t; + (* Blocks received so far *) + blocks_table : Block_hash.t Delegate_Map.t HLevel.t; + (* Maximum delta of level to register *) + preserved_levels : int; + (* Highest level seen in a block *) + mutable highest_level_encountered : Raw_level.t; +} + +let create_state ~preserved_levels = + Lwt.return + { + endorsements_table = HLevel.create preserved_levels; + blocks_table = HLevel.create preserved_levels; + preserved_levels; + highest_level_encountered = Raw_level.root (* 0l *); + } + +(* We choose a previous offset (5 blocks from head) to ensure that the + injected operation is branched from a valid predecessor. *) +let get_block_offset level = + match Raw_level.of_int32 5l with + | Ok min_level -> + Lwt.return (if Raw_level.(level < min_level) then `Head 0 else `Head 5) + | Error errs -> + let errs = Environment.wrap_tztrace errs in + lwt_log_error + Tag.DSL.( + fun f -> + f "Invalid level conversion : %a" + -% t event "invalid_level_conversion" + -% a errs_tag errs) + >>= fun () -> Lwt.return (`Head 0) + +let process_endorsements (cctxt : #Protocol_client_context.full) state + (endorsements : Alpha_block_services.operation list) level = + List.iter_es + (fun {Alpha_block_services.shell; chain_id; receipt; hash; protocol_data; _} + -> + let chain = `Hash chain_id in + match (protocol_data, receipt) with + | ( Operation_data + { contents = + Single + (Endorsement_with_slot + { endorsement = + { protocol_data = + {contents = Single (Endorsement _); _} as + protocol_data; + _ }; + _ }); + _ }, + Some + Apply_results.( + Operation_metadata + { contents = + Single_result + (Endorsement_with_slot_result + (Endorsement_result {delegate; slots = slot :: _; _})) + }) ) -> ( + let new_endorsement : Kind.endorsement Alpha_context.operation = + {shell; protocol_data} + in + let map = + Option.value ~default:Delegate_Map.empty + @@ HLevel.find state.endorsements_table (chain_id, level) + in + (* If a previous endorsement made by this pkh is found for + the same level we inject a double_endorsement *) + match Delegate_Map.find delegate map with + | None -> + return + @@ HLevel.add + state.endorsements_table + (chain_id, level) + (Delegate_Map.add delegate new_endorsement map) + | Some existing_endorsement + when Block_hash.( + existing_endorsement.shell.branch + <> new_endorsement.shell.branch) -> + get_block_offset level + >>= fun block -> + Alpha_block_services.hash cctxt ~chain ~block () + >>=? fun block_hash -> + Alpha_services.Forge.double_endorsement_evidence + cctxt + (`Hash chain_id, block) + ~branch:block_hash + ~op1:existing_endorsement + ~op2:new_endorsement + ~slot + () + >>=? fun bytes -> + let bytes = Signature.concat bytes Signature.zero in + lwt_log_notice + Tag.DSL.( + fun f -> + f "Double endorsement detected" + -% t event "double_endorsement_detected" + -% t + conflicting_endorsements_tag + (existing_endorsement, new_endorsement)) + >>= fun () -> + (* A denunciation may have already occurred *) + Shell_services.Injection.operation cctxt ~chain bytes + >>=? fun op_hash -> + lwt_log_notice + Tag.DSL.( + fun f -> + f "Double endorsement evidence injected %a" + -% t event "double_endorsement_denounced" + -% t signed_operation_tag bytes + -% a Operation_hash.Logging.tag op_hash) + >>= fun () -> + return + @@ HLevel.replace + state.endorsements_table + (chain_id, level) + (Delegate_Map.add delegate new_endorsement map) + | Some _ -> + (* This endorsement is already present in another + block but endorse the same predecessor *) + return_unit ) + | _ -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Inconsistent endorsement found %a" + -% t event "inconsistent_endorsement" + -% a Operation_hash.Logging.tag hash) + >>= fun () -> return_unit) + endorsements + >>=? fun () -> return_unit + +let process_block (cctxt : #Protocol_client_context.full) state + (header : Alpha_block_services.block_info) = + match header with + | {hash; metadata = None; _} -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Unexpected pruned block: %a" + -% t event "unexpected_pruned_block" + -% a Block_hash.Logging.tag hash) + >>= fun () -> return_unit + | { Alpha_block_services.chain_id; + hash; + metadata = Some {protocol_data = {baker; level = {level; _}; _}; _}; + _ } -> ( + let chain = `Hash chain_id in + let map = + match HLevel.find state.blocks_table (chain_id, level) with + | None -> + Delegate_Map.empty + | Some x -> + x + in + match Delegate_Map.find baker map with + | None -> + return + @@ HLevel.add + state.blocks_table + (chain_id, level) + (Delegate_Map.add baker hash map) + | Some existing_hash when Block_hash.( = ) existing_hash hash -> + (* This case should never happen *) + lwt_debug + Tag.DSL.( + fun f -> + f + "Double baking detected but block hashes are equivalent. \ + Skipping..." + -% t event "double_baking_but_not") + >>= fun () -> + return + @@ HLevel.replace + state.blocks_table + (chain_id, level) + (Delegate_Map.add baker hash map) + | Some existing_hash -> + (* If a previous endorsement made by this pkh is found for + the same level we inject a double_endorsement *) + Alpha_block_services.header + cctxt + ~chain + ~block:(`Hash (existing_hash, 0)) + () + >>=? fun ({shell; protocol_data; _} : + Alpha_block_services.block_header) -> + let bh1 = {Alpha_context.Block_header.shell; protocol_data} in + Alpha_block_services.header cctxt ~chain ~block:(`Hash (hash, 0)) () + >>=? fun ({shell; protocol_data; _} : + Alpha_block_services.block_header) -> + let bh2 = {Alpha_context.Block_header.shell; protocol_data} in + (* If the blocks are on different chains then skip it *) + get_block_offset level + >>= fun block -> + Alpha_block_services.hash cctxt ~chain ~block () + >>=? fun block_hash -> + Alpha_services.Forge.double_baking_evidence + cctxt + (chain, block) + ~branch:block_hash + ~bh1 + ~bh2 + () + >>=? fun bytes -> + let bytes = Signature.concat bytes Signature.zero in + lwt_log_notice + Tag.DSL.( + fun f -> + f "Double baking detected" -% t event "double_baking_detected") + >>= fun () -> + (* A denunciation may have already occurred *) + Shell_services.Injection.operation cctxt ~chain bytes + >>=? fun op_hash -> + lwt_log_notice + Tag.DSL.( + fun f -> + f "Double baking evidence injected %a" + -% t event "double_baking_denounced" + -% t signed_operation_tag bytes + -% a Operation_hash.Logging.tag op_hash) + >>= fun () -> + return + @@ HLevel.replace + state.blocks_table + (chain_id, level) + (Delegate_Map.add baker hash map) ) + +(* Remove levels that are lower than the [highest_level_encountered] minus [preserved_levels] *) +let cleanup_old_operations state = + let highest_level_encountered = + Int32.to_int (Raw_level.to_int32 state.highest_level_encountered) + in + let diff = highest_level_encountered - state.preserved_levels in + let threshold = + if diff < 0 then Raw_level.root + else + Raw_level.of_int32 (Int32.of_int diff) + |> function Ok threshold -> threshold | Error _ -> Raw_level.root + in + let filter hmap = + HLevel.filter_map_inplace + (fun (_, level) x -> + if Raw_level.(level < threshold) then None else Some x) + hmap + in + filter state.endorsements_table ; + filter state.blocks_table ; + () + +let endorsements_index = 0 + +(* Each new block is processed : + - Checking that every endorser operated only once at this level + - Checking that every baker injected only once at this level +*) +let process_new_block (cctxt : #Protocol_client_context.full) state + {hash; chain_id; level; protocol; next_protocol; _} = + if Protocol_hash.(protocol <> next_protocol) then + lwt_log_error + Tag.DSL.( + fun f -> + f "Protocol changing detected. Skipping the block." + -% t event "protocol_change_detected" + (* TODO which protocols -- in tag *)) + >>= fun () -> return_unit + else + lwt_debug + Tag.DSL.( + fun f -> + f "Block level : %a" + -% t event "accuser_saw_block" + -% a level_tag level + -% t Block_hash.Logging.tag hash) + >>= fun () -> + let chain = `Hash chain_id in + let block = `Hash (hash, 0) in + state.highest_level_encountered <- + Raw_level.max level state.highest_level_encountered ; + (* Processing blocks *) + Alpha_block_services.info cctxt ~chain ~block () + >>= (function + | Ok block_info -> + process_block cctxt state block_info + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Error while fetching operations in block %a@\n%a" + -% t event "fetch_operations_error" + -% a Block_hash.Logging.tag hash + -% a errs_tag errs) + >>= fun () -> return_unit) + >>=? fun () -> + (* Processing endorsements *) + Alpha_block_services.Operations.operations cctxt ~chain ~block () + >>= (function + | Ok operations -> ( + match List.nth operations endorsements_index with + | Some endorsements -> + process_endorsements cctxt state endorsements level + | None -> + return_unit ) + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Error while fetching operations in block %a@\n%a" + -% t event "fetch_operations_error" + -% a Block_hash.Logging.tag hash + -% a errs_tag errs) + >>= fun () -> return_unit) + >>=? fun () -> + cleanup_old_operations state ; + return_unit + +let create (cctxt : #Protocol_client_context.full) ~preserved_levels + valid_blocks_stream = + let process_block cctxt state bi = + process_new_block cctxt state bi + >>= function + | Ok () -> + lwt_log_notice + Tag.DSL.( + fun f -> + f "Block %a registered" + -% t event "accuser_processed_block" + -% a Block_hash.Logging.tag bi.Client_baking_blocks.hash) + >>= return + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Error while processing block %a@\n%a" + -% t event "accuser_block_error" + -% a Block_hash.Logging.tag bi.hash + -% a errs_tag errs) + >>= return + in + let state_maker _ = create_state ~preserved_levels >>= return in + Client_baking_scheduling.main + ~name:"accuser" + ~cctxt + ~stream:valid_blocks_stream + ~state_maker + ~pre_loop:(fun _ _ _ -> return_unit) + ~compute_timeout:(fun _ -> Lwt_utils.never_ending ()) + ~timeout_k:(fun _ _ () -> return_unit) + ~event_k:process_block + ~finalizer:(fun _ -> Lwt.return_unit) diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_denunciation.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_denunciation.mli new file mode 100644 index 0000000000000000000000000000000000000000..963ff969f83c1a9ea821eea26b196e5c814c20d2 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_denunciation.mli @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val create : + #Protocol_client_context.full -> + preserved_levels:int -> + Client_baking_blocks.block_info tzresult Lwt_stream.t -> + unit tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_endorsement.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_endorsement.ml new file mode 100644 index 0000000000000000000000000000000000000000..c322cd2f1d49f2ebefc16a664ad67e7e26e77334 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_endorsement.ml @@ -0,0 +1,381 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context + +include Internal_event.Legacy_logging.Make_semantic (struct + let name = Protocol.name ^ ".baking.endorsement" +end) + +open Logging + +let get_signing_slots cctxt ~chain ~block delegate level = + Alpha_services.Delegate.Endorsing_rights.get + cctxt + ~levels:[level] + ~delegates:[delegate] + (chain, block) + >>=? function [{slots; _}] -> return_some slots | _ -> return_none + +let inject_endorsement (cctxt : #Protocol_client_context.full) ?async ~chain + ~block hash level delegate_sk delegate_pkh = + Alpha_services.Delegate.Endorsing_rights.get + cctxt + ~levels:[level] + ~delegates:[delegate_pkh] + (chain, block) + >>=? function + | [{slots = []; _}] | [] | _ :: _ :: _ -> + assert false + | [{slots = slot :: _; _}] -> + Alpha_services.Forge.endorsement + cctxt + (chain, block) + ~branch:hash + ~level + () + >>=? fun bytes -> + let wallet = (cctxt :> Client_context.wallet) in + (* Double-check the right to inject an endorsement *) + let open Client_baking_highwatermarks in + wallet#with_lock (fun () -> + Client_baking_files.resolve_location cctxt ~chain `Endorsement + >>=? fun endorsement_location -> + may_inject_endorsement + cctxt + endorsement_location + ~delegate:delegate_pkh + level + >>=? function + | true -> + record_endorsement + cctxt + endorsement_location + ~delegate:delegate_pkh + level + >>=? fun () -> return_true + | false -> + return_false) + >>=? fun is_allowed_to_endorse -> + if is_allowed_to_endorse then + Chain_services.chain_id cctxt ~chain () + >>=? fun chain_id -> + Client_keys.append + cctxt + delegate_sk + ~watermark:(Endorsement chain_id) + bytes + >>=? fun signed_bytes -> + (* wrap the legacy endorsement in a slot-bearing wrapper *) + match + Data_encoding.Binary.of_bytes_opt + Alpha_context.Operation.encoding + signed_bytes + with + | Some + { shell; + protocol_data = + Operation_data + ({contents = Single (Endorsement _); _} as protocol_data) } + -> + let wrapped = + { + shell; + protocol_data = + Operation_data + { + contents = + Single + (Endorsement_with_slot + {endorsement = {shell; protocol_data}; slot}); + signature = None; + }; + } + in + let wrapped_bytes = + Data_encoding.Binary.to_bytes_exn + Alpha_context.Operation.encoding + wrapped + in + Shell_services.Injection.operation + cctxt + ?async + ~chain + wrapped_bytes + >>=? fun oph -> return oph + | _ -> + assert false + else + lwt_log_error + Tag.DSL.( + fun f -> + f "Level %a : previously endorsed." + -% t event "double_endorsement_near_miss" + -% a level_tag level) + >>= fun () -> fail (Level_previously_endorsed level) + +let forge_endorsement (cctxt : #Protocol_client_context.full) ?async ~chain + ~block ~src_sk src_pk = + let src_pkh = Signature.Public_key.hash src_pk in + Alpha_block_services.metadata cctxt ~chain ~block () + >>=? fun {protocol_data = {level = {level; _}; _}; _} -> + Shell_services.Blocks.hash cctxt ~chain ~block () + >>=? fun hash -> + inject_endorsement cctxt ?async ~chain ~block hash level src_sk src_pkh + >>=? fun oph -> + Client_keys.get_key cctxt src_pkh + >>=? fun (name, _pk, _sk) -> + lwt_log_notice + Tag.DSL.( + fun f -> + f "Injected endorsement for block '%a' (level %a, contract %s) '%a'" + -% t event "injected_endorsement" + -% a Block_hash.Logging.tag hash + -% a level_tag level + -% s Client_keys.Logging.tag name + -% t Signature.Public_key_hash.Logging.tag src_pkh + -% a Operation_hash.Logging.tag oph) + >>= fun () -> return oph + +(** Worker *) + +(* because of delegates *) +[@@@ocaml.warning "-30"] + +type state = { + delegates : public_key_hash list; + delay : int64; + mutable pending : endorsements option; +} + +and endorsements = { + time : Time.Protocol.t; + delegates : public_key_hash list; + block : Client_baking_blocks.block_info; +} + +[@@@ocaml.warning "+30"] + +let create_state delegates delay = {delegates; delay; pending = None} + +let get_delegates cctxt state = + match state.delegates with + | [] -> + Client_keys.get_keys cctxt + >>=? fun keys -> + let delegates = List.map (fun (_, pkh, _, _) -> pkh) keys in + return Signature.Public_key_hash.Set.(delegates |> of_list |> elements) + | _ :: _ as delegates -> + return delegates + +let endorse_for_delegate cctxt block delegate_pkh = + let {Client_baking_blocks.hash; level; chain_id; _} = block in + Client_keys.get_key cctxt delegate_pkh + >>=? fun (name, _pk, delegate_sk) -> + lwt_debug + Tag.DSL.( + fun f -> + f "Endorsing %a for %s (level %a)!" + -% t event "endorsing" + -% a Block_hash.Logging.tag hash + -% s Client_keys.Logging.tag name + -% a level_tag level) + >>= fun () -> + let chain = `Hash chain_id in + let block = `Hash (hash, 0) in + inject_endorsement cctxt ~chain ~block hash level delegate_sk delegate_pkh + >>=? fun oph -> + lwt_log_notice + Tag.DSL.( + fun f -> + f "Injected endorsement for block '%a' (level %a, contract %s) '%a'" + -% t event "injected_endorsement" + -% a Block_hash.Logging.tag hash + -% a level_tag level + -% s Client_keys.Logging.tag name + -% t Signature.Public_key_hash.Logging.tag delegate_pkh + -% a Operation_hash.Logging.tag oph) + >>= fun () -> return_unit + +let allowed_to_endorse cctxt bi delegate = + Client_keys.Public_key_hash.name cctxt delegate + >>=? fun name -> + lwt_debug + Tag.DSL.( + fun f -> + f "Checking if allowed to endorse block %a for %s" + -% t event "check_endorsement_ok" + -% a Block_hash.Logging.tag bi.Client_baking_blocks.hash + -% s Client_keys.Logging.tag name) + >>= fun () -> + let chain = `Hash bi.chain_id in + let block = `Hash (bi.hash, 0) in + let level = bi.level in + get_signing_slots cctxt ~chain ~block delegate level + >>=? function + | None | Some [] -> + lwt_debug + Tag.DSL.( + fun f -> + f "No slot found for %a/%s" + -% t event "endorsement_no_slots_found" + -% a Block_hash.Logging.tag bi.hash + -% s Client_keys.Logging.tag name) + >>= fun () -> return_false + | Some (_ :: _ as slots) -> ( + lwt_debug + Tag.DSL.( + fun f -> + f "Found slots for %a/%s (%a)" + -% t event "endorsement_slots_found" + -% a Block_hash.Logging.tag bi.hash + -% s Client_keys.Logging.tag name + -% a endorsement_slots_tag slots) + >>= fun () -> + cctxt#with_lock (fun () -> + Client_baking_files.resolve_location cctxt ~chain `Endorsement + >>=? fun endorsement_location -> + Client_baking_highwatermarks.may_inject_endorsement + cctxt + endorsement_location + ~delegate + level) + >>=? function + | false -> + lwt_debug + Tag.DSL.( + fun f -> + f "Level %a (or higher) previously endorsed: do not endorse." + -% t event "previously_endorsed" + -% a level_tag level) + >>= fun () -> return_false + | true -> + return_true ) + +let prepare_endorsement ~(max_past : int64) () + (cctxt : #Protocol_client_context.full) state bi = + let past = + Time.Protocol.diff + (Time.System.to_protocol (Systime_os.now ())) + bi.Client_baking_blocks.timestamp + in + if past > max_past then + lwt_log_info + Tag.DSL.( + fun f -> + f "Ignore block %a: forged too far the past" + -% t event "endorsement_stale_block" + -% a Block_hash.Logging.tag bi.hash) + >>= fun () -> return_unit + else + lwt_log_info + Tag.DSL.( + fun f -> + f "Received new block %a" + -% t event "endorsement_got_block" + -% a Block_hash.Logging.tag bi.hash) + >>= fun () -> + let time = + Time.Protocol.add + (Time.System.to_protocol (Systime_os.now ())) + state.delay + in + get_delegates cctxt state + >>=? fun delegates -> + List.filter_ep (allowed_to_endorse cctxt bi) delegates + >>=? fun delegates -> + state.pending <- Some {time; block = bi; delegates} ; + return_unit + +let compute_timeout state = + match state.pending with + | None -> + Lwt_utils.never_ending () + | Some {time; block; delegates} -> ( + match Client_baking_scheduling.sleep_until time with + | None -> + Lwt.return (block, delegates) + | Some timeout -> + let timespan = + let timespan = + Ptime.diff (Time.System.of_protocol_exn time) (Systime_os.now ()) + in + if Ptime.Span.compare timespan Ptime.Span.zero > 0 then timespan + else Ptime.Span.zero + in + lwt_log_info + Tag.DSL.( + fun f -> + f "Waiting until %a (%a) to inject endorsements" + -% t event "wait_before_injecting" + -% a timestamp_tag (Time.System.of_protocol_exn time) + -% a timespan_tag timespan) + >>= fun () -> timeout >>= fun () -> Lwt.return (block, delegates) ) + +let create (cctxt : #Protocol_client_context.full) ?(max_past = 110L) ~delay + delegates block_stream = + let state_maker _ = + let state = create_state delegates (Int64.of_int delay) in + return state + in + let timeout_k cctxt state (block, delegates) = + state.pending <- None ; + List.iter_es + (fun delegate -> + endorse_for_delegate cctxt block delegate + >>= function + | Ok () -> + return_unit + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f + "@[Error while injecting endorsement for delegate %a \ + : @[%a@]@]@." + -% t event "error_while_endorsing" + -% a Signature.Public_key_hash.Logging.tag delegate + -% a errs_tag errs) + >>= fun () -> + (* We continue anyway *) + return_unit) + delegates + in + let event_k cctxt state bi = + state.pending <- None ; + prepare_endorsement ~max_past () cctxt state bi + in + Client_baking_scheduling.main + ~name:"endorser" + ~cctxt + ~stream:block_stream + ~state_maker + ~pre_loop:(prepare_endorsement ~max_past ()) + ~compute_timeout + ~timeout_k + ~event_k + ~finalizer:(fun _ -> Lwt.return_unit) diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_endorsement.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_endorsement.mli new file mode 100644 index 0000000000000000000000000000000000000000..c03d37c2048ec99ca3c6a2c27a493dd284710a7b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_endorsement.mli @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2018 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** [forge_endorsement cctxt blk ~src_sk src_pk] emits an endorsement + operation for the block [blk] +*) +val forge_endorsement : + #Protocol_client_context.full -> + ?async:bool -> + chain:Chain_services.chain -> + block:Block_services.block -> + src_sk:Client_keys.sk_uri -> + public_key -> + Operation_hash.t tzresult Lwt.t + +val create : + #Protocol_client_context.full -> + ?max_past:int64 (* number of seconds *) -> + delay:int -> + public_key_hash list -> + Client_baking_blocks.block_info tzresult Lwt_stream.t -> + unit tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_files.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_files.ml new file mode 100644 index 0000000000000000000000000000000000000000..10e5844ea8e2951defef651c5d6fe4b423062147 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_files.ml @@ -0,0 +1,60 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type _ location = {filename : string; chain : Chain_services.chain} + +let resolve_location (cctxt : #Client_context.full) ~chain (kind : 'a) : + 'a location tzresult Lwt.t = + let basename = + match kind with + | `Block -> + "block" + | `Endorsement -> + "endorsement" + | `Nonce -> + "nonce" + in + let test_filename chain_id = + Format.kasprintf return "test_%a_%s" Chain_id.pp_short chain_id basename + in + ( match chain with + | `Main -> + return basename + | `Test -> + (* FIXME: dead code. Cannot be removed because the type + Chain_services.chain is common to all the + protocols. *) + Chain_services.chain_id cctxt ~chain:`Test () + >>=? fun chain_id -> test_filename chain_id + | `Hash chain_id -> + Chain_services.chain_id cctxt ~chain:`Main () + >>=? fun main_chain_id -> + if Chain_id.(chain_id = main_chain_id) then return basename + else test_filename chain_id ) + >>=? fun filename -> return {filename; chain} + +let filename {filename; _} = filename + +let chain {chain; _} = chain diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_files.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_files.mli new file mode 100644 index 0000000000000000000000000000000000000000..a01f0b6a775c03f7f0aa2ad6b806ff8c178269df --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_files.mli @@ -0,0 +1,36 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type _ location + +val resolve_location : + #Client_context.full -> + chain:Chain_services.chain -> + ([< `Block | `Endorsement | `Nonce] as 'kind) -> + 'kind location tzresult Lwt.t + +val filename : _ location -> string + +val chain : _ location -> Chain_services.chain diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_forge.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_forge.ml new file mode 100644 index 0000000000000000000000000000000000000000..2a3cba4ac8a4ab96d593a79a2948d8643e6fc8da --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_forge.ml @@ -0,0 +1,1676 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context + +include Internal_event.Legacy_logging.Make_semantic (struct + let name = Protocol.name ^ ".baking.forge" +end) + +open Logging + +(* The index of the different components of the protocol's validation passes *) +(* TODO: ideally, we would like this to be more abstract and possibly part of + the protocol, while retaining the generality of lists *) +(* Hypothesis : we suppose [List.length Protocol.Main.validation_passes = 4] *) +let endorsements_index = 0 + +let votes_index = 1 + +let anonymous_index = 2 + +let managers_index = 3 + +let default_max_priority = 64 + +let default_minimal_fees = + match Tez.of_mutez 100L with None -> assert false | Some t -> t + +let default_minimal_nanotez_per_gas_unit = Q.of_int 100 + +let default_minimal_nanotez_per_byte = Q.of_int 1000 + +let default_retry_counter = 5 + +type slot = + Time.Protocol.t * (Client_baking_blocks.block_info * int * public_key_hash) + +type state = { + context_path : string; + mutable index : Context.index; + (* Nonces file location *) + nonces_location : [`Nonce] Client_baking_files.location; + (* see [get_delegates] below to find delegates when the list is empty *) + delegates : public_key_hash list; + (* lazy-initialisation with retry-on-error *) + constants : Constants.t; + (* Minimal operation fee required to include an operation in a block *) + minimal_fees : Tez.t; + (* Minimal operation fee per gas required to include an operation in a block *) + minimal_nanotez_per_gas_unit : Q.t; + (* Minimal operation fee per byte required to include an operation in a block *) + minimal_nanotez_per_byte : Q.t; + (* truly mutable *) + mutable best_slot : slot option; + mutable retry_counter : int; +} + +let create_state ?(minimal_fees = default_minimal_fees) + ?(minimal_nanotez_per_gas_unit = default_minimal_nanotez_per_gas_unit) + ?(minimal_nanotez_per_byte = default_minimal_nanotez_per_byte) + ?(retry_counter = default_retry_counter) context_path index nonces_location + delegates constants = + { + context_path; + index; + nonces_location; + delegates; + constants; + minimal_fees; + minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte; + best_slot = None; + retry_counter; + } + +let get_delegates cctxt state = + match state.delegates with + | [] -> + Client_keys.get_keys cctxt + >>=? fun keys -> return (List.map (fun (_, pkh, _, _) -> pkh) keys) + | _ -> + return state.delegates + +let generate_seed_nonce () = + match Nonce.of_bytes (Rand.generate Constants.nonce_length) with + | Error _errs -> + assert false + | Ok nonce -> + nonce + +let forge_block_header (cctxt : #Protocol_client_context.full) ~chain block + delegate_sk shell priority seed_nonce_hash = + Client_baking_pow.mine cctxt chain block shell (fun proof_of_work_nonce -> + {Block_header.priority; seed_nonce_hash; proof_of_work_nonce}) + >>=? fun contents -> + let unsigned_header = + Data_encoding.Binary.to_bytes_exn + Alpha_context.Block_header.unsigned_encoding + (shell, contents) + in + Shell_services.Chain.chain_id cctxt ~chain () + >>=? fun chain_id -> + Client_keys.append + cctxt + delegate_sk + ~watermark:(Block_header chain_id) + unsigned_header + +let forge_faked_protocol_data ~priority ~seed_nonce_hash = + Alpha_context.Block_header. + { + contents = + { + priority; + seed_nonce_hash; + proof_of_work_nonce = Client_baking_pow.empty_proof_of_work_nonce; + }; + signature = Signature.zero; + } + +let assert_valid_operations_hash shell_header operations = + let operations_hash = + Operation_list_list_hash.compute + (List.map + Operation_list_hash.compute + (List.map (List.map Tezos_base.Operation.hash) operations)) + in + fail_unless + (Operation_list_list_hash.equal + operations_hash + shell_header.Tezos_base.Block_header.operations_hash) + (failure "Client_baking_forge.inject_block: inconsistent header.") + +let compute_endorsing_power cctxt ~chain ~block operations = + Shell_services.Chain.chain_id cctxt ~chain () + >>=? fun chain_id -> + List.fold_left_es + (fun sum -> function + | { Alpha_context.protocol_data = + Operation_data {contents = Single (Endorsement_with_slot _); _}; + _ } as op -> ( + Delegate_services.Endorsing_power.get + cctxt + (chain, block) + op + chain_id + >>= function + | Error _ -> + (* Filters invalid endorsements *) + return sum + | Ok power -> + return (sum + power) ) | _ -> return sum) + 0 + operations + +let inject_block cctxt ?(force = false) ?seed_nonce_hash ~chain ~shell_header + ~priority ~delegate_pkh ~delegate_sk ~level operations = + assert_valid_operations_hash shell_header operations + >>=? fun () -> + let block = `Hash (shell_header.Tezos_base.Block_header.predecessor, 0) in + forge_block_header + cctxt + ~chain + block + delegate_sk + shell_header + priority + seed_nonce_hash + >>=? fun signed_header -> + (* Record baked blocks to prevent double baking *) + let open Client_baking_highwatermarks in + cctxt#with_lock (fun () -> + Client_baking_files.resolve_location cctxt ~chain `Block + >>=? fun block_location -> + may_inject_block cctxt block_location ~delegate:delegate_pkh level + >>=? function + | true -> + record_block cctxt block_location ~delegate:delegate_pkh level + >>=? fun () -> return_true + | false -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Level %a : previously baked" + -% t event "double_bake_near_miss" + -% a level_tag level) + >>= fun () -> return force) + >>=? function + | false -> + fail (Level_previously_baked level) + | true -> + Shell_services.Injection.block + cctxt + ~force + ~chain + signed_header + operations + >>=? fun block_hash -> + lwt_log_info + Tag.DSL.( + fun f -> + f "Client_baking_forge.inject_block: inject %a" + -% t event "inject_baked_block" + -% a Block_hash.Logging.tag block_hash + -% t signed_header_tag signed_header + -% t operations_tag operations) + >>= fun () -> return block_hash + +type error += Failed_to_preapply of Tezos_base.Operation.t * error list + +let () = + register_error_kind + `Permanent + ~id:"Client_baking_forge.failed_to_preapply" + ~title:"Fail to preapply an operation" + ~description:"" + ~pp:(fun ppf (op, err) -> + let h = Tezos_base.Operation.hash op in + Format.fprintf + ppf + "@[Failed to preapply %a:@ @[%a@]@]" + Operation_hash.pp_short + h + pp_print_error + err) + Data_encoding.( + obj2 + (req "operation" (dynamic_size Tezos_base.Operation.encoding)) + (req "error" RPC_error.encoding)) + (function Failed_to_preapply (hash, err) -> Some (hash, err) | _ -> None) + (fun (hash, err) -> Failed_to_preapply (hash, err)) + +type manager_content = { + total_fee : Tez.t; + total_gas : Fixed_point_repr.integral_tag Gas.Arith.t; + source : public_key_hash; + counter : counter; +} + +let get_manager_content op = + let {protocol_data = Operation_data {contents; _}; _} = op in + let open Operation in + let l = to_list (Contents_list contents) in + List.fold_left_e + (fun ((first_source, first_counter, total_fee, total_gas) as acc) -> + function + | Contents (Manager_operation {source; counter; fee; gas_limit; _}) -> + (Environment.wrap_tzresult @@ Tez.(total_fee +? fee)) + >>? fun total_fee -> + (* There is only one unique source per packed transaction *) + let first_source = Option.value ~default:source first_source in + (* We only care about the first counter *) + let first_counter = Option.value ~default:counter first_counter in + ok + ( Some first_source, + Some first_counter, + total_fee, + Gas.Arith.add total_gas gas_limit ) | _ -> ok acc) + (None, None, Tez.zero, Gas.Arith.zero) + l + |> function + | Ok (Some source, Some counter, total_fee, total_gas) -> + Some {total_fee; total_gas; source; counter} + | _ -> + None + +(* Sort operation considering potential gas and storage usage. + Weight = fee / (max ( (size/size_total), (gas/gas_total))) *) +let sort_manager_operations ~max_size ~hard_gas_limit_per_block ~minimal_fees + ~minimal_nanotez_per_gas_unit ~minimal_nanotez_per_byte + (operations : packed_operation list) = + let compute_weight op (fee, gas) = + let size = Data_encoding.Binary.length Operation.encoding op in + let size_f = Q.of_int size in + let gas_f = Q.of_bigint (Gas.Arith.integral_to_z gas) in + let fee_f = Q.of_int64 (Tez.to_mutez fee) in + let size_ratio = Q.(size_f / Q.of_int max_size) in + let gas_ratio = + Q.( + gas_f / Q.of_bigint (Gas.Arith.integral_to_z hard_gas_limit_per_block)) + in + (size, gas, Q.(fee_f / max size_ratio gas_ratio)) + in + List.filter_map + (fun op -> + match get_manager_content op with + | None -> + None + | Some {total_fee; total_gas; source; counter} -> + if Tez.(total_fee < minimal_fees) then None + else + let (size, gas, weight_ratio) = + compute_weight op (total_fee, total_gas) + in + let fees_in_nanotez = + Q.mul (Q.of_int64 (Tez.to_mutez total_fee)) (Q.of_int 1000) + in + let enough_fees_for_gas = + let minimal_fees_in_nanotez = + Q.mul + minimal_nanotez_per_gas_unit + (Q.of_bigint @@ Gas.Arith.integral_to_z gas) + in + Q.compare minimal_fees_in_nanotez fees_in_nanotez <= 0 + in + let enough_fees_for_size = + let minimal_fees_in_nanotez = + Q.mul minimal_nanotez_per_byte (Q.of_int size) + in + Q.compare minimal_fees_in_nanotez fees_in_nanotez <= 0 + in + if enough_fees_for_size && enough_fees_for_gas then + Some (op, weight_ratio, source, counter) + else None) + operations + |> fun operations -> + (* We order the operations by their weights except if they belong + to the same manager, if they do, we order them by their + counter. *) + let compare (_op, weight_ratio, source, counter) + (_op', weight_ratio', source', counter') = + (* Be careful with the [compare]s *) + if Signature.Public_key_hash.equal source source' then + (* we want the smallest counter first *) + Z.compare counter counter' + else + (* We want the biggest weight first *) + Q.compare weight_ratio' weight_ratio + in + List.sort compare operations |> List.map (fun (op, _, _, _) -> op) + +let retain_operations_up_to_quota operations quota = + let {Tezos_protocol_environment.max_op; max_size} = quota in + let operations = + match max_op with Some n -> List.sub operations n | None -> operations + in + let exception Full of packed_operation list in + let operations = + try + List.fold_left + (fun (ops, size) op -> + let operation_size = + Data_encoding.Binary.length Alpha_context.Operation.encoding op + in + let new_size = size + operation_size in + if new_size > max_size then raise (Full ops) + else (op :: ops, new_size)) + ([], 0) + operations + |> fst + with Full ops -> ops + in + List.rev operations + +let trim_manager_operations ~max_size ~hard_gas_limit_per_block + manager_operations = + let manager_operations = + List.filter_map + (fun op -> + match get_manager_content op with + | Some {total_gas; _} -> + let size = Data_encoding.Binary.length Operation.encoding op in + Some (op, (size, total_gas)) + | None -> + None) + manager_operations + in + List.fold_left + (fun (total_size, total_gas, (good_ops, bad_ops)) (op, (size, gas)) -> + let new_size = total_size + size in + let new_gas = Gas.Arith.(add total_gas gas) in + if new_size > max_size || Gas.Arith.(new_gas > hard_gas_limit_per_block) + then (new_size, new_gas, (good_ops, op :: bad_ops)) + else (new_size, new_gas, (op :: good_ops, bad_ops))) + (0, Gas.Arith.zero, ([], [])) + manager_operations + |> fun (_, _, (good_ops, bad_ops)) -> + (* We keep the overflowing operations, it may be used for client-side validation *) + (List.rev good_ops, List.rev bad_ops) + +(* We classify operations, sort managers operation by interest and add bad ones at the end *) +(* Hypothesis : we suppose that the received manager operations have a valid gas_limit *) + +(** [classify_operations] classify the operation in 4 lists indexed as such : + - 0 -> Endorsements + - 1 -> Votes and proposals + - 2 -> Anonymous operations + - 3 -> High-priority manager operations. + Returns two list : + - A desired set of operations to be included + - Potentially overflowing operations *) +let classify_operations (cctxt : #Protocol_client_context.full) ~chain ~block + ~hard_gas_limit_per_block ~minimal_fees ~minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte (ops : packed_operation list) = + Alpha_block_services.live_blocks cctxt ~chain ~block () + >>=? fun live_blocks -> + let t = + (* Remove operations that are too old *) + let ops = + List.filter + (fun {shell = {branch; _}; _} -> Block_hash.Set.mem branch live_blocks) + ops + in + let validation_passes_len = List.length Main.validation_passes in + let t = Array.make validation_passes_len [] in + List.iter + (fun (op : packed_operation) -> + List.iter + (fun pass -> t.(pass) <- op :: t.(pass)) + (Main.acceptable_passes op)) + ops ; + Array.map List.rev t + in + let overflowing_manager_operations = + (* Retrieve the optimist maximum paying manager operations *) + let manager_operations = t.(managers_index) in + let {Environment.Updater.max_size; _} = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth Main.validation_passes managers_index + in + let ordered_operations = + sort_manager_operations + ~max_size + ~hard_gas_limit_per_block + ~minimal_fees + ~minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte + manager_operations + in + (* Greedy heuristic *) + let (desired_manager_operations, overflowing_manager_operations) = + trim_manager_operations + ~max_size + ~hard_gas_limit_per_block + ordered_operations + in + t.(managers_index) <- desired_manager_operations ; + ok overflowing_manager_operations + in + Lwt.return + ( overflowing_manager_operations + >>? fun overflowing_manager_operations -> + ok (Array.to_list t, overflowing_manager_operations) ) + +let forge (op : Operation.packed) : Operation.raw = + { + shell = op.shell; + proto = + Data_encoding.Binary.to_bytes_exn + Alpha_context.Operation.protocol_data_encoding + op.protocol_data; + } + +let ops_of_mempool (ops : Alpha_block_services.Mempool.t) = + (* We only retain the applied, unprocessed and delayed operations *) + List.rev + ( Operation_hash.Map.fold (fun _ op acc -> op :: acc) ops.unprocessed + @@ Operation_hash.Map.fold + (fun _ (op, _) acc -> op :: acc) + ops.branch_delayed + @@ List.rev_map (fun (_, op) -> op) ops.applied ) + +let unopt_operations cctxt chain mempool = function + | None -> ( + match mempool with + | None -> + Alpha_block_services.Mempool.pending_operations cctxt ~chain () + >>=? fun mpool -> + let ops = ops_of_mempool mpool in + return ops + | Some file -> + Tezos_stdlib_unix.Lwt_utils_unix.Json.read_file file + >>=? fun json -> + let mpool = + Data_encoding.Json.destruct + Alpha_block_services.S.Mempool.encoding + json + in + let ops = ops_of_mempool mpool in + return ops ) + | Some operations -> + return operations + +let all_ops_valid (results : error Preapply_result.t list) = + let open Operation_hash.Map in + List.for_all + (fun (result : error Preapply_result.t) -> + is_empty result.refused + && is_empty result.branch_refused + && is_empty result.branch_delayed) + results + +let decode_priority cctxt chain block ~priority ~endorsing_power = + match priority with + | `Set priority -> + Alpha_services.Delegate.Minimal_valid_time.get + cctxt + (chain, block) + priority + endorsing_power + >>=? fun minimal_timestamp -> return (priority, minimal_timestamp) + | `Auto (src_pkh, max_priority) -> ( + Alpha_services.Helpers.current_level cctxt ~offset:1l (chain, block) + >>=? fun {level; _} -> + Alpha_services.Delegate.Baking_rights.get + cctxt + ?max_priority + ~levels:[level] + ~delegates:[src_pkh] + (chain, block) + >>=? fun possibilities -> + match + List.find + (fun p -> p.Alpha_services.Delegate.Baking_rights.level = level) + possibilities + with + | Some {Alpha_services.Delegate.Baking_rights.priority = prio; _} -> + Alpha_services.Delegate.Minimal_valid_time.get + cctxt + (chain, block) + prio + endorsing_power + >>=? fun minimal_timestamp -> return (prio, minimal_timestamp) + | None -> + failwith "No slot found at level %a" Raw_level.pp level ) + +let unopt_timestamp ?(force = false) timestamp minimal_timestamp = + let timestamp = + match timestamp with + | None -> + minimal_timestamp + | Some timestamp -> + timestamp + in + if (not force) && timestamp < minimal_timestamp then + failwith + "Proposed timestamp %a is earlier than minimal timestamp %a" + Time.Protocol.pp_hum + timestamp + Time.Protocol.pp_hum + minimal_timestamp + else return timestamp + +let merge_preapps (old : error Preapply_result.t) + (neu : error Preapply_result.t) = + let merge _ a b = + (* merge ops *) + match (a, b) with + | (None, None) -> + None + | (Some x, None) -> + Some x + | (_, Some y) -> + Some y + in + let merge = Operation_hash.Map.merge merge in + (* merge op maps *) + (* merge preapplies *) + { + Preapply_result.applied = []; + refused = merge old.refused neu.refused; + branch_refused = merge old.branch_refused neu.branch_refused; + branch_delayed = merge old.branch_delayed neu.branch_delayed; + } + +let error_of_op (result : error Preapply_result.t) op = + let op = forge op in + let h = Tezos_base.Operation.hash op in + match Operation_hash.Map.find h result.refused with + | Some (_, trace) -> + Some (Failed_to_preapply (op, trace)) + | None -> ( + match Operation_hash.Map.find h result.branch_refused with + | Some (_, trace) -> + Some (Failed_to_preapply (op, trace)) + | None -> ( + match Operation_hash.Map.find h result.branch_delayed with + | Some (_, trace) -> + Some (Failed_to_preapply (op, trace)) + | None -> + None ) ) + +let filter_and_apply_operations cctxt state ~chain ~block block_info ~priority + ?protocol_data + ((operations : packed_operation list list), overflowing_operations) = + (* Retrieve the minimal valid time for when the block can be baked with 0 endorsements *) + Delegate_services.Minimal_valid_time.get cctxt (chain, block) priority 0 + >>=? fun min_valid_timestamp -> + let open Client_baking_simulator in + lwt_debug + Tag.DSL.( + fun f -> + f "starting client-side validation after %a" + -% t event "baking_local_validation_start" + -% a Block_hash.Logging.tag block_info.Client_baking_blocks.hash) + >>= fun () -> + begin_construction + ~timestamp:min_valid_timestamp + ?protocol_data + state.index + block_info + >>= (function + | Ok inc -> + return inc + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Error while fetching current context : %a" + -% t event "context_fetch_error" + -% a errs_tag errs) + >>= fun () -> + lwt_log_notice + Tag.DSL.( + fun f -> + f "Retrying to open the context" -% t event "reopen_context") + >>= fun () -> + Client_baking_simulator.load_context + ~context_path:state.context_path + >>= fun index -> + begin_construction + ~timestamp:min_valid_timestamp + ?protocol_data + index + block_info + >>=? fun inc -> + state.index <- index ; + return inc) + >>=? fun initial_inc -> + let endorsements = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth operations endorsements_index + in + let votes = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth operations votes_index + in + let anonymous = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth operations anonymous_index + in + let managers = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth operations managers_index + in + let validate_operation inc op = + protect (fun () -> add_operation inc op) + >>= function + | Error errs -> + lwt_debug + Tag.DSL.( + fun f -> + f + "@[Client-side validation: filtered invalid operation %a@\n\ + %a@]" + -% t event "baking_rejected_invalid_operation" + -% a Operation_hash.Logging.tag (Operation.hash_packed op) + -% a errs_tag errs) + >>= fun () -> Lwt.return_none + | Ok (resulting_state, receipt) -> ( + try + (* Check that the metadata are serializable/deserializable *) + let _ = + Data_encoding.Binary.( + of_bytes_exn + Protocol.operation_receipt_encoding + (to_bytes_exn Protocol.operation_receipt_encoding receipt)) + in + Lwt.return_some resulting_state + with exn -> + lwt_debug + Tag.DSL.( + fun f -> + f "Client-side validation: filtered invalid operation %a" + -% t event "baking_rejected_invalid_operation" + -% a + errs_tag + [ Validation_errors.Cannot_serialize_operation_metadata; + Exn exn ]) + >>= fun () -> Lwt.return_none ) + in + let filter_valid_operations inc ops = + List.fold_left_s + (fun (inc, acc) op -> + validate_operation inc op + >>= function + | None -> + Lwt.return (inc, acc) + | Some inc' -> + Lwt.return (inc', op :: acc)) + (inc, []) + ops + >>= fun (inc, ops) -> Lwt.return (inc, List.rev ops) + in + (* First pass : we filter out invalid operations by applying them in the correct order *) + filter_valid_operations initial_inc endorsements + >>= fun (inc, endorsements) -> + filter_valid_operations inc votes + >>= fun (inc, votes) -> + filter_valid_operations inc anonymous + >>= fun (manager_inc, anonymous) -> + filter_valid_operations manager_inc (managers @ overflowing_operations) + >>= fun (inc, managers) -> + finalize_construction inc + >>=? fun _ -> + let quota : Environment.Updater.quota list = Main.validation_passes in + let {Constants.hard_gas_limit_per_block; _} = state.constants.parametric in + let votes = + retain_operations_up_to_quota + votes + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth quota votes_index) + in + let anonymous = + retain_operations_up_to_quota + anonymous + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth quota anonymous_index) + in + (* We found a valid subset of managers, trim them *) + let (accepted_managers, _overflowing_managers) = + trim_manager_operations + ~max_size: + ( WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth quota managers_index ) + .max_size + ~hard_gas_limit_per_block + managers + in + (* Second pass : make sure we only keep valid operations *) + filter_valid_operations manager_inc accepted_managers + >>= fun (_, accepted_managers) -> + let operations = [endorsements; votes; anonymous; accepted_managers] in + (* Construct a context with the valid operations and a correct timestamp *) + compute_endorsing_power cctxt ~chain ~block endorsements + >>=? fun current_endorsing_power -> + Delegate_services.Minimal_valid_time.get + cctxt + (chain, block) + priority + current_endorsing_power + >>=? fun expected_validity -> + (* Finally, we construct a block with the minimal possible timestamp + given the endorsing power *) + begin_construction + ~timestamp:expected_validity + ?protocol_data + state.index + block_info + >>=? fun inc -> + List.fold_left_es + (fun inc op -> add_operation inc op >>=? fun (inc, _receipt) -> return inc) + inc + (List.flatten operations) + >>=? fun final_inc -> + finalize_construction final_inc + >>=? fun (validation_result, metadata) -> + return + (final_inc, (validation_result, metadata), operations, expected_validity) + +(* Build the block header : mimics node prevalidation *) +let finalize_block_header shell_header ~timestamp validation_result operations + predecessor_block_metadata_hash predecessor_ops_metadata_hash = + let {Tezos_protocol_environment.context; fitness; message; _} = + validation_result + in + let validation_passes = List.length Main.validation_passes in + let operations_hash : Operation_list_list_hash.t = + Operation_list_list_hash.compute + (List.map + (fun sl -> + Operation_list_hash.compute (List.map Operation.hash_packed sl)) + operations) + in + let context = Shell_context.unwrap_disk_context context in + ( match predecessor_block_metadata_hash with + | Some predecessor_block_metadata_hash -> + Context.add_predecessor_block_metadata_hash + context + predecessor_block_metadata_hash + | None -> + Lwt.return context ) + >>= fun context -> + ( match predecessor_ops_metadata_hash with + | Some predecessor_ops_metadata_hash -> + Context.add_predecessor_ops_metadata_hash + context + predecessor_ops_metadata_hash + | None -> + Lwt.return context ) + >>= fun context -> + let context = Context.hash ~time:timestamp ?message context in + let header = + Tezos_base.Block_header. + { + shell_header with + level = Int32.succ shell_header.level; + validation_passes; + operations_hash; + fitness; + context; + } + in + return header + +let forge_block cctxt ?force ?operations ?(best_effort = operations = None) + ?(sort = best_effort) ?(minimal_fees = default_minimal_fees) + ?(minimal_nanotez_per_gas_unit = default_minimal_nanotez_per_gas_unit) + ?(minimal_nanotez_per_byte = default_minimal_nanotez_per_byte) ?timestamp + ?mempool ?context_path ?seed_nonce_hash ~chain ~priority ~delegate_pkh + ~delegate_sk block = + (* making the arguments usable *) + unopt_operations cctxt chain mempool operations + >>=? fun operations_arg -> + compute_endorsing_power cctxt ~chain ~block operations_arg + >>=? fun endorsing_power -> + decode_priority cctxt chain block ~priority ~endorsing_power + >>=? fun (priority, minimal_timestamp) -> + unopt_timestamp ?force timestamp minimal_timestamp + >>=? fun timestamp -> + (* get basic building blocks *) + let protocol_data = forge_faked_protocol_data ~priority ~seed_nonce_hash in + Alpha_services.Constants.all cctxt (chain, block) + >>=? fun Constants. + { parametric = {hard_gas_limit_per_block; endorsers_per_block; _}; + _ } -> + classify_operations + cctxt + ~chain + ~hard_gas_limit_per_block + ~block + ~minimal_fees + ~minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte + operations_arg + >>=? fun (operations, overflowing_ops) -> + (* Ensure that we retain operations up to the quota *) + let quota : Environment.Updater.quota list = Main.validation_passes in + let endorsements = + List.sub + ( WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth operations endorsements_index ) + endorsers_per_block + in + let votes = + retain_operations_up_to_quota + ( WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth operations votes_index ) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth quota votes_index) + in + let anonymous = + retain_operations_up_to_quota + ( WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth operations anonymous_index ) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth quota anonymous_index) + in + (* Size/Gas check already occurred in classify operations *) + let managers = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth operations managers_index + in + let operations = [endorsements; votes; anonymous; managers] in + ( match context_path with + | None -> + Alpha_block_services.Helpers.Preapply.block + cctxt + ~chain + ~block + ~timestamp + ~sort + ~protocol_data + operations + >>=? fun (shell_header, result) -> + let operations = + List.map (fun l -> List.map snd l.Preapply_result.applied) result + in + (* everything went well (or we don't care about errors): GO! *) + if best_effort || all_ops_valid result then + return (shell_header, operations) + (* some errors (and we care about them) *) + else + let result = + List.fold_left merge_preapps Preapply_result.empty result + in + Lwt.return_error @@ List.filter_map (error_of_op result) operations_arg + | Some context_path -> + assert sort ; + assert best_effort ; + Context.init ~readonly:true context_path + >>= fun index -> + Client_baking_blocks.info cctxt ~chain block + >>=? fun bi -> + Alpha_services.Constants.all cctxt (chain, `Head 0) + >>=? fun constants -> + Client_baking_files.resolve_location cctxt ~chain `Nonce + >>=? fun nonces_location -> + let state = + { + context_path; + index; + nonces_location; + constants; + delegates = []; + best_slot = None; + minimal_fees = default_minimal_fees; + minimal_nanotez_per_gas_unit = default_minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte = default_minimal_nanotez_per_byte; + retry_counter = default_retry_counter; + } + in + filter_and_apply_operations + cctxt + state + ~chain + ~block + ~priority + ~protocol_data + bi + (operations, overflowing_ops) + >>=? fun ( final_context, + (validation_result, _), + operations, + min_valid_timestamp ) -> + let current_protocol = bi.next_protocol in + let context = + Shell_context.unwrap_disk_context validation_result.context + in + Context.get_protocol context + >>= fun next_protocol -> + if Protocol_hash.equal current_protocol next_protocol then + finalize_block_header + final_context.header + ~timestamp:min_valid_timestamp + validation_result + operations + bi.predecessor_block_metadata_hash + bi.predecessor_operations_metadata_hash + >>= function + | Error _ as errs -> + Lwt.return errs + | Ok shell_header -> + return (shell_header, List.map (List.map forge) operations) + else + lwt_log_notice + Tag.DSL.( + fun f -> + f "New protocol detected: using shell validation" + -% t event "shell_prevalidation_notice") + >>= fun () -> + Alpha_block_services.Helpers.Preapply.block + cctxt + ~chain + ~block + ~timestamp:min_valid_timestamp + ~sort + ~protocol_data + operations + >>=? fun (shell_header, _result) -> + return (shell_header, List.map (List.map forge) operations) ) + >>=? fun (shell_header, operations) -> + (* Now for some logging *) + let total_op_count = List.length operations_arg in + let valid_op_count = List.length (List.concat operations) in + lwt_log_notice + Tag.DSL.( + fun f -> + f + "found %d valid operations (%d refused) for timestamp %a (fitness %a)" + -% t event "found_valid_operations" + -% s valid_ops valid_op_count + -% s refused_ops (total_op_count - valid_op_count) + -% a timestamp_tag (Time.System.of_protocol_exn timestamp) + -% a fitness_tag shell_header.fitness) + >>= fun () -> + ( match Raw_level.of_int32 shell_header.level with + | Ok level -> + return level + | Error errs -> + let errs = Environment.wrap_tztrace errs in + lwt_log_error + Tag.DSL.( + fun f -> + f "Error on raw_level conversion : %a" + -% t event "block_injection_failed" + -% a errs_tag errs) + >>= fun () -> Lwt.return_error errs ) + >>=? fun level -> + inject_block + cctxt + ?force + ~chain + ~shell_header + ~priority + ?seed_nonce_hash + ~delegate_pkh + ~delegate_sk + ~level + operations + >>= function + | Ok hash -> + return hash + | Error errs as error -> + lwt_log_error + Tag.DSL.( + fun f -> + f + "@[Error while injecting block@ @[Included operations : \ + %a@]@ %a@]" + -% t event "block_injection_failed" + -% a raw_operations_tag (List.concat operations) + -% a errs_tag errs) + >>= fun () -> Lwt.return error + +let shell_prevalidation (cctxt : #Protocol_client_context.full) ~chain ~block + ~timestamp seed_nonce_hash operations + ((_, (bi, priority, delegate)) as _slot) = + let protocol_data = forge_faked_protocol_data ~priority ~seed_nonce_hash in + Alpha_block_services.Helpers.Preapply.block + cctxt + ~chain + ~block + ~timestamp + ~sort:true + ~protocol_data + operations + >>= function + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f + "Shell-side validation: error while prevalidating operations:@\n\ + %a" + -% t event "built_invalid_block_error" + -% a errs_tag errs) + >>= fun () -> return_none + | Ok (shell_header, operations) -> + let raw_ops = + List.map (fun l -> List.map snd l.Preapply_result.applied) operations + in + return_some + (bi, priority, shell_header, raw_ops, delegate, seed_nonce_hash) + +let filter_outdated_endorsements expected_level ops = + List.filter + (function + | { Alpha_context.protocol_data = + Operation_data + { contents = + Single + (Endorsement_with_slot + { endorsement = + { protocol_data = + {contents = Single (Endorsement {level; _}); _}; + _ }; + _ }); + _ }; + _ } -> + Raw_level.equal expected_level level + | _ -> + true) + ops + +(** [fetch_operations] retrieve the operations present in the + mempool. If no endorsements are present in the initial set, it + waits until it's able to build a valid block. *) +let fetch_operations (cctxt : #Protocol_client_context.full) ~chain + (_, (head, priority, _delegate)) = + Alpha_block_services.Mempool.monitor_operations + cctxt + ~chain + ~applied:true + ~branch_delayed:true + ~refused:false + ~branch_refused:false + () + >>=? fun (operation_stream, _stop) -> + (* Hypothesis : the first call to the stream returns instantly, even if the mempool is empty. *) + Lwt_stream.get operation_stream + >>= function + | None -> + (* New head received : aborting block construction *) + return_none + | Some current_mempool -> + let block = `Hash (head.Client_baking_blocks.hash, 0) in + let operations = + ref (filter_outdated_endorsements head.level current_mempool) + in + (* Actively request our peers' for missing operations *) + Shell_services.Mempool.request_operations cctxt ~chain () + >>=? fun () -> + let compute_minimal_valid_time () = + compute_endorsing_power cctxt ~chain ~block !operations + >>=? fun current_endorsing_power -> + Delegate_services.Minimal_valid_time.get + cctxt + (chain, block) + priority + current_endorsing_power + in + let compute_timeout () = + compute_minimal_valid_time () + >>=? fun expected_validity -> + match Client_baking_scheduling.sleep_until expected_validity with + | None -> + return_unit + | Some timeout -> + timeout >>= fun () -> return_unit + in + let last_get_event = ref None in + let get_event () = + match !last_get_event with + | None -> + let t = Lwt_stream.get operation_stream in + last_get_event := Some t ; + t + | Some t -> + t + in + let rec loop () = + Lwt.choose + [ (compute_timeout () >|= fun _ -> `Timeout); + (get_event () >|= fun e -> `Event e) ] + >>= function + | `Event (Some op_list) -> + last_get_event := None ; + let op_list = filter_outdated_endorsements head.level op_list in + operations := op_list @ !operations ; + loop () + | `Timeout -> + (* Retrieve the remaining operations present in the stream + before block construction *) + let remaining_operations = + filter_outdated_endorsements + head.level + (List.flatten (Lwt_stream.get_available operation_stream)) + in + operations := remaining_operations @ !operations ; + compute_minimal_valid_time () + >>=? fun expected_validity -> + return_some (!operations, expected_validity) + | `Event None -> + (* Got new head while waiting: + - not enough endorsements received ; + - late at baking *) + return_none + in + loop () + +(** Given a delegate baking slot [build_block] constructs a full block + with consistent operations that went through the client-side + validation *) +let build_block cctxt ~user_activated_upgrades state seed_nonce_hash + ((slot_timestamp, (bi, priority, delegate)) as slot) = + let chain = `Hash bi.Client_baking_blocks.chain_id in + let block = `Hash (bi.hash, 0) in + Alpha_services.Helpers.current_level cctxt ~offset:1l (chain, block) + >>=? fun next_level -> + let seed_nonce_hash = + if next_level.expected_commitment then Some seed_nonce_hash else None + in + Client_keys.Public_key_hash.name cctxt delegate + >>=? fun name -> + lwt_debug + Tag.DSL.( + fun f -> + f "Try baking after %a (slot %d) for %s (%a)" + -% t event "try_baking" + -% a Block_hash.Logging.tag bi.hash + -% s bake_priority_tag priority + -% s Client_keys.Logging.tag name + -% a timestamp_tag (Time.System.of_protocol_exn slot_timestamp)) + >>= fun () -> + fetch_operations cctxt ~chain slot + >>=? function + | None -> + lwt_log_notice + Tag.DSL.( + fun f -> + f + "Received a new head while waiting for operations. Aborting \ + this block." + -% t event "new_head_received") + >>= fun () -> return_none + | Some (operations, timestamp) -> ( + classify_operations + cctxt + ~chain + ~hard_gas_limit_per_block: + state.constants.parametric.hard_gas_limit_per_block + ~minimal_fees:state.minimal_fees + ~minimal_nanotez_per_gas_unit:state.minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte:state.minimal_nanotez_per_byte + ~block + operations + >>=? fun (operations, overflowing_ops) -> + let next_version = + match + Tezos_base.Block_header.get_forced_protocol_upgrade + ~user_activated_upgrades + ~level:(Raw_level.to_int32 next_level.level) + with + | None -> + bi.next_protocol + | Some hash -> + hash + in + if Protocol_hash.(Protocol.hash <> next_version) then + (* Let the shell validate this *) + shell_prevalidation + cctxt + ~chain + ~block + ~timestamp + seed_nonce_hash + operations + slot + else + let protocol_data = + forge_faked_protocol_data ~priority ~seed_nonce_hash + in + filter_and_apply_operations + cctxt + state + ~chain + ~block + ~priority + ~protocol_data + bi + (operations, overflowing_ops) + >>= function + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f + "Client-side validation: error while filtering invalid \ + operations :@\n\ + @[%a@]" + -% t event "client_side_validation_error" + -% a errs_tag errs) + >>= fun () -> + lwt_log_notice + Tag.DSL.( + fun f -> + f "Building a block using shell validation" + -% t event "shell_prevalidation_notice") + >>= fun () -> + shell_prevalidation + cctxt + ~chain + ~block + ~timestamp + seed_nonce_hash + operations + slot + | Ok + (final_context, (validation_result, _), operations, valid_timestamp) + -> + ( if + Time.System.(Systime_os.now () < of_protocol_exn valid_timestamp) + then + lwt_log_notice + Tag.DSL.( + fun f -> + f "[%a] not ready to inject yet, waiting until %a" + -% a timestamp_tag (Systime_os.now ()) + -% a + timestamp_tag + (Time.System.of_protocol_exn valid_timestamp) + -% t event "waiting_before_injection") + >>= fun () -> + match Client_baking_scheduling.sleep_until valid_timestamp with + | None -> + Lwt.return_unit + | Some timeout -> + timeout + else Lwt.return_unit ) + >>= fun () -> + lwt_debug + Tag.DSL.( + fun f -> + f + "Try forging locally the block header for %a (slot %d) \ + for %s (%a)" + -% t event "try_forging" + -% a Block_hash.Logging.tag bi.hash + -% s bake_priority_tag priority + -% s Client_keys.Logging.tag name + -% a timestamp_tag (Time.System.of_protocol_exn timestamp)) + >>= fun () -> + let current_protocol = bi.next_protocol in + let context = + Shell_context.unwrap_disk_context validation_result.context + in + Context.get_protocol context + >>= fun next_protocol -> + if Protocol_hash.equal current_protocol next_protocol then + finalize_block_header + final_context.header + ~timestamp:valid_timestamp + validation_result + operations + bi.predecessor_block_metadata_hash + bi.predecessor_operations_metadata_hash + >>= function + | Error _ as errs -> + Lwt.return errs + | Ok shell_header -> + let raw_ops = List.map (List.map forge) operations in + return_some + ( bi, + priority, + shell_header, + raw_ops, + delegate, + seed_nonce_hash ) + else + lwt_log_notice + Tag.DSL.( + fun f -> + f "New protocol detected: using shell validation" + -% t event "shell_prevalidation_notice") + >>= fun () -> + shell_prevalidation + cctxt + ~chain + ~block + ~timestamp + seed_nonce_hash + operations + slot ) + +(** [bake cctxt state] create a single block when woken up to do + so. All the necessary information is available in the + [state.best_slot]. *) +let bake (cctxt : #Protocol_client_context.full) ~user_activated_upgrades + ~chain state = + ( match state.best_slot with + | None -> + assert false (* unreachable *) + | Some slot -> + return slot ) + >>=? fun slot -> + let seed_nonce = generate_seed_nonce () in + let seed_nonce_hash = Nonce.hash seed_nonce in + build_block cctxt ~user_activated_upgrades state seed_nonce_hash slot + >>=? function + | Some (head, priority, shell_header, operations, delegate, seed_nonce_hash) + -> ( + let level = Raw_level.succ head.level in + Client_keys.Public_key_hash.name cctxt delegate + >>=? fun name -> + lwt_log_info + Tag.DSL.( + fun f -> + f "Injecting block (priority %d, fitness %a) for %s after %a..." + -% t event "start_injecting_block" + -% s bake_priority_tag priority + -% a fitness_tag shell_header.fitness + -% s Client_keys.Logging.tag name + -% a Block_hash.Logging.predecessor_tag shell_header.predecessor + -% t Signature.Public_key_hash.Logging.tag delegate) + >>= fun () -> + Client_keys.get_key cctxt delegate + >>=? fun (_, _, delegate_sk) -> + inject_block + cctxt + ~chain + ~force:false + ~shell_header + ~priority + ?seed_nonce_hash + ~delegate_pkh:delegate + ~delegate_sk + ~level + operations + >>= function + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f + "@[Error while injecting block@ @[Included operations \ + : %a@]@ %a@]" + -% t event "block_injection_failed" + -% a raw_operations_tag (List.concat operations) + -% a errs_tag errs) + >>= fun () -> return_unit + | Ok block_hash -> + lwt_log_notice + Tag.DSL.( + fun f -> + f + "Injected block %a for %s after %a (level %a, priority %d, \ + fitness %a, operations %a)." + -% t event "injected_block" + -% a Block_hash.Logging.tag block_hash + -% s Client_keys.Logging.tag name + -% a Block_hash.Logging.tag shell_header.predecessor + -% a level_tag level + -% s bake_priority_tag priority + -% a fitness_tag shell_header.fitness + -% a operations_tag operations) + >>= fun () -> + ( if seed_nonce_hash <> None then + cctxt#with_lock (fun () -> + let open Client_baking_nonces in + load cctxt state.nonces_location + >>=? fun nonces -> + let nonces = add nonces block_hash seed_nonce in + save cctxt state.nonces_location nonces) + |> trace_exn (Failure "Error while recording nonce") + else return_unit ) + >>=? fun () -> return_unit ) + | None -> + return_unit + +(** [get_baking_slots] calls the node via RPC to retrieve the potential + slots for the given delegates within a given range of priority *) +let get_baking_slots cctxt ?(max_priority = default_max_priority) new_head + delegates = + let chain = `Hash new_head.Client_baking_blocks.chain_id in + let block = `Hash (new_head.hash, 0) in + let level = Raw_level.succ new_head.level in + Alpha_services.Delegate.Baking_rights.get + cctxt + ~max_priority + ~levels:[level] + ~delegates + (chain, block) + >>= function + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Error while fetching baking possibilities:\n%a" + -% t event "baking_slot_fetch_errors" + -% a errs_tag errs) + >>= fun () -> Lwt.return_nil + | Ok [] -> + Lwt.return_nil + | Ok slots -> + let slots = + List.filter_map + (function + | {Alpha_services.Delegate.Baking_rights.timestamp = None; _} -> + None + | {timestamp = Some timestamp; priority; delegate; _} -> + Some (timestamp, (new_head, priority, delegate))) + slots + in + Lwt.return slots + +(** [compute_best_slot_on_current_level] retrieves, among the given + delegates, the highest priority slot for the current level. Then, + it registers this slot in the state so the timeout knows when to + wake up. *) +let compute_best_slot_on_current_level ?max_priority + (cctxt : #Protocol_client_context.full) state new_head = + get_delegates cctxt state + >>=? fun delegates -> + let level = Raw_level.succ new_head.Client_baking_blocks.level in + get_baking_slots cctxt ?max_priority new_head delegates + >>= function + | [] -> + lwt_log_notice + Tag.DSL.( + fun f -> + let max_priority = + Option.value ~default:default_max_priority max_priority + in + f "No slot found at level %a (max_priority = %d)" + -% t event "no_slot_found" -% a level_tag level + -% s bake_priority_tag max_priority) + >>= fun () -> return_none + (* No slot found *) + | h :: t -> + (* One or more slot found, fetching the best (lowest) priority. + We do not suppose that the received slots are sorted. *) + let ((timestamp, (_, priority, delegate)) as best_slot) = + List.fold_left + (fun ((_, (_, priority, _)) as acc) ((_, (_, priority', _)) as slot) -> + if priority < priority' then acc else slot) + h + t + in + Client_keys.Public_key_hash.name cctxt delegate + >>=? fun name -> + lwt_log_notice + Tag.DSL.( + fun f -> + f + "New baking slot found (level %a, priority %d) at %a for %s \ + after %a." + -% t event "have_baking_slot" -% a level_tag level + -% s bake_priority_tag priority + -% a timestamp_tag (Time.System.of_protocol_exn timestamp) + -% s Client_keys.Logging.tag name + -% a Block_hash.Logging.tag new_head.hash + -% t Signature.Public_key_hash.Logging.tag delegate) + >>= fun () -> + (* Found at least a slot *) + return_some best_slot + +(** [reveal_potential_nonces] reveal registered nonces *) +let reveal_potential_nonces (cctxt : #Client_context.full) constants ~chain + ~block = + cctxt#with_lock (fun () -> + Client_baking_files.resolve_location cctxt ~chain `Nonce + >>=? fun nonces_location -> + Client_baking_nonces.load cctxt nonces_location + >>= function + | Error err -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Cannot read nonces: %a" -% t event "read_nonce_fail" + -% a errs_tag err) + >>= fun () -> return_unit + | Ok nonces -> ( + Client_baking_nonces.get_unrevealed_nonces + cctxt + nonces_location + nonces + >>= function + | Error err -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Cannot retrieve unrevealed nonces: %a" + -% t event "nonce_retrieval_fail" + -% a errs_tag err) + >>= fun () -> return_unit + | Ok [] -> + return_unit + | Ok nonces_to_reveal -> ( + Client_baking_revelation.inject_seed_nonce_revelation + cctxt + ~chain + ~block + nonces_to_reveal + >>= function + | Error err -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Cannot inject nonces: %a" + -% t event "nonce_injection_fail" + -% a errs_tag err) + >>= fun () -> return_unit + | Ok () -> + (* If some nonces are to be revealed it means: + - We entered a new cycle and we can clear old nonces ; + - A revelation was not included yet in the cycle beginning. + So, it is safe to only filter outdated_nonces there *) + Client_baking_nonces.filter_outdated_nonces + cctxt + ~constants + nonces_location + nonces + >>=? fun live_nonces -> + Client_baking_nonces.save cctxt nonces_location live_nonces + >>=? fun () -> return_unit ) )) + +(** [create] starts the main loop of the baker. The loop monitors new blocks and + starts individual baking operations when baking-slots are available to any of + the [delegates] *) +let create (cctxt : #Protocol_client_context.full) ~user_activated_upgrades + ?minimal_fees ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte + ?max_priority ~chain ~context_path delegates block_stream = + let state_maker bi = + Alpha_services.Constants.all cctxt (chain, `Head 0) + >>=? fun constants -> + Client_baking_simulator.load_context ~context_path + >>= fun index -> + Client_baking_simulator.check_context_consistency + index + bi.Client_baking_blocks.context + >>=? fun () -> + Client_baking_files.resolve_location cctxt ~chain `Nonce + >>=? fun nonces_location -> + let state = + create_state + ?minimal_fees + ?minimal_nanotez_per_gas_unit + ?minimal_nanotez_per_byte + context_path + index + nonces_location + delegates + constants + in + return state + in + let event_k cctxt state new_head = + reveal_potential_nonces + cctxt + state.constants + ~chain + ~block:(`Hash (new_head.Client_baking_blocks.hash, 0)) + >>= fun _ignore_nonce_err -> + compute_best_slot_on_current_level ?max_priority cctxt state new_head + >>=? fun slot -> + state.best_slot <- slot ; + return_unit + in + let compute_timeout state = + match state.best_slot with + | None -> + (* No slot, just wait for new blocks which will give more info *) + Lwt_utils.never_ending () + | Some (timestamp, _) -> ( + match Client_baking_scheduling.sleep_until timestamp with + | None -> + Lwt.return_unit + | Some timeout -> + timeout ) + in + let timeout_k cctxt state () = + bake cctxt ~user_activated_upgrades ~chain state + >>= function + | Error err -> + if state.retry_counter = 0 then ( + (* Stop the timeout and wait for the next block *) + state.best_slot <- None ; + state.retry_counter <- default_retry_counter ; + Lwt.return (Error err) ) + else + lwt_log_error + Tag.DSL.( + fun f -> + f "Retrying after baking error %a" + -% t event "retrying_on_error" + -% a errs_tag err) + >>= fun () -> + state.retry_counter <- pred state.retry_counter ; + return_unit + | Ok () -> + (* Stop the timeout and wait for the next block *) + state.best_slot <- None ; + state.retry_counter <- default_retry_counter ; + return_unit + in + let finalizer state = Context.close state.index in + Client_baking_scheduling.main + ~name:"baker" + ~cctxt + ~stream:block_stream + ~state_maker + ~pre_loop:event_k + ~compute_timeout + ~timeout_k + ~event_k + ~finalizer diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_forge.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_forge.mli new file mode 100644 index 0000000000000000000000000000000000000000..508e06a270e708603827c8aaef8d71d78b735789 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_forge.mli @@ -0,0 +1,106 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** [generate_seed_nonce ()] is a random nonce that is typically used + in block headers. When baking, bakers generate random nonces whose + hash is committed in the block they bake. They will typically + reveal the aforementioned nonce during the next cycle. *) +val generate_seed_nonce : unit -> Nonce.t + +(** [inject_block cctxt blk ?force ~priority ~timestamp ~fitness + ~seed_nonce ~src_sk ops] tries to inject a block in the node. If + [?force] is set, the fitness check will be bypassed. [priority] + will be used to compute the baking slot (level is + precomputed). [src_sk] is used to sign the block header. *) +val inject_block : + #Protocol_client_context.full -> + ?force:bool -> + ?seed_nonce_hash:Nonce_hash.t -> + chain:Chain_services.chain -> + shell_header:Block_header.shell_header -> + priority:int -> + delegate_pkh:Signature.Public_key_hash.t -> + delegate_sk:Client_keys.sk_uri -> + level:Raw_level.t -> + Operation.raw list list -> + Block_hash.t tzresult Lwt.t + +type error += Failed_to_preapply of Tezos_base.Operation.t * error list + +(** [forge_block cctxt ?fee_threshold ?force ?operations ?best_effort + ?sort ?timestamp ?max_priority ?priority ~seed_nonce ~src_sk + pk_hash parent_blk] injects a block in the node. In addition of inject_block, + it will: + + * Operations: If [?operations] is [None], it will get pending + operations and add them to the block. Otherwise, provided + operations will be used. In both cases, they will be validated. + + * Baking priority: If [`Auto] is used, it will be computed from + the public key hash of the specified contract, optionally capped + to a maximum value, and optionally restricting for free baking slot. + + * Timestamp: If [?timestamp] is set, and is compatible with the + computed baking priority, it will be used. Otherwise, it will be + set at the best baking priority. + + * Fee Threshold: If [?fee_threshold] is given, operations with fees lower than it + are not added to the block. +*) +val forge_block : + #Protocol_client_context.full -> + ?force:bool -> + ?operations:Operation.packed list -> + ?best_effort:bool -> + ?sort:bool -> + ?minimal_fees:Tez.t -> + ?minimal_nanotez_per_gas_unit:Q.t -> + ?minimal_nanotez_per_byte:Q.t -> + ?timestamp:Time.Protocol.t -> + ?mempool:string -> + ?context_path:string -> + ?seed_nonce_hash:Nonce_hash.t -> + chain:Chain_services.chain -> + priority:[`Set of int | `Auto of public_key_hash * int option] -> + delegate_pkh:Signature.Public_key_hash.t -> + delegate_sk:Client_keys.sk_uri -> + Block_services.block -> + Block_hash.t tzresult Lwt.t + +val create : + #Protocol_client_context.full -> + user_activated_upgrades:User_activated.upgrades -> + ?minimal_fees:Tez.t -> + ?minimal_nanotez_per_gas_unit:Q.t -> + ?minimal_nanotez_per_byte:Q.t -> + ?max_priority:int -> + chain:Chain_services.chain -> + context_path:string -> + public_key_hash list -> + Client_baking_blocks.block_info tzresult Lwt_stream.t -> + unit tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_highwatermarks.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_highwatermarks.ml new file mode 100644 index 0000000000000000000000000000000000000000..c2b8c4068fcb60b9d236f3821e9b0b4511f91157 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_highwatermarks.ml @@ -0,0 +1,120 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Protocol +open Alpha_context + +type error += Level_previously_endorsed of Raw_level.t + +type error += Level_previously_baked of Raw_level.t + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"highwatermarks.block_already_baked" + ~title:"Block already baked" + ~description:"Trying to bake a block for a level that was previously done" + ~pp:(fun ppf level -> + Format.fprintf ppf "Level %a previously baked " Raw_level.pp level) + (obj1 (req "level" Raw_level.encoding)) + (function Level_previously_baked level -> Some level | _ -> None) + (fun level -> Level_previously_baked level) ; + register_error_kind + `Permanent + ~id:"highwatermarks.block_already_endorsed" + ~title:"Fail to preapply an operation" + ~description: + "Trying to endorse a block for a level that was previously done" + ~pp:(fun ppf level -> + Format.fprintf ppf "Level %a previously endorsed " Raw_level.pp level) + (obj1 (req "level" Raw_level.encoding)) + (function Level_previously_endorsed level -> Some level | _ -> None) + (fun level -> Level_previously_endorsed level) + +type t = (string * Raw_level.t) list + +let encoding = + let open Data_encoding in + def "highwatermarks" @@ assoc Raw_level.encoding + +let empty = [] + +(* We do not lock these functions. The caller will be already locked. *) +let load_highwatermarks (cctxt : #Protocol_client_context.full) filename : + t tzresult Lwt.t = + cctxt#load filename encoding ~default:empty + +let save_highwatermarks (cctxt : #Protocol_client_context.full) filename + highwatermarks : unit tzresult Lwt.t = + cctxt#write filename highwatermarks encoding + +let retrieve_highwatermark cctxt filename = load_highwatermarks cctxt filename + +let may_inject (cctxt : #Protocol_client_context.full) location ~delegate level + = + retrieve_highwatermark cctxt (Client_baking_files.filename location) + >>=? fun highwatermark -> + let delegate = Signature.Public_key_hash.to_short_b58check delegate in + List.find_opt + (fun (delegate', _) -> String.compare delegate delegate' = 0) + highwatermark + |> function + | None -> + return_true + | Some (_, past_level) -> + return Raw_level.(past_level < level) + +let may_inject_block = may_inject + +let may_inject_endorsement = may_inject + +let record (cctxt : #Protocol_client_context.full) location ~delegate level = + let filename = Client_baking_files.filename location in + let delegate = Signature.Public_key_hash.to_short_b58check delegate in + load_highwatermarks cctxt filename + >>=? fun highwatermarks -> + let level = + match List.assoc_opt delegate highwatermarks with + | None -> + level + | Some lower_prev_level when level >= lower_prev_level -> + level + | Some higher_prev_level -> + higher_prev_level + (* should only happen in `forced` mode *) + in + save_highwatermarks + cctxt + filename + ( (delegate, level) + :: List.filter + (fun (delegate', _) -> String.compare delegate delegate' <> 0) + highwatermarks ) + +let record_block = record + +let record_endorsement = record diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_highwatermarks.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_highwatermarks.mli new file mode 100644 index 0000000000000000000000000000000000000000..2dd35c1ff7770157f6361c801636c63cc72310b1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_highwatermarks.mli @@ -0,0 +1,63 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type error += Level_previously_endorsed of Raw_level.t + +type error += Level_previously_baked of Raw_level.t + +type t + +val encoding : t Data_encoding.t + +val may_inject_block : + #Protocol_client_context.full -> + [`Block] Client_baking_files.location -> + delegate:Signature.public_key_hash -> + Raw_level.t -> + bool tzresult Lwt.t + +val may_inject_endorsement : + #Protocol_client_context.full -> + [`Endorsement] Client_baking_files.location -> + delegate:Signature.public_key_hash -> + Raw_level.t -> + bool tzresult Lwt.t + +val record_block : + #Protocol_client_context.full -> + [`Block] Client_baking_files.location -> + delegate:Signature.public_key_hash -> + Raw_level.t -> + unit tzresult Lwt.t + +val record_endorsement : + #Protocol_client_context.full -> + [`Endorsement] Client_baking_files.location -> + delegate:Signature.public_key_hash -> + Raw_level.t -> + unit tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_lib.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_lib.ml new file mode 100644 index 0000000000000000000000000000000000000000..face4ba87e2cab04f1f057255ad447d39786268d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_lib.ml @@ -0,0 +1,170 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let bake_block (cctxt : #Protocol_client_context.full) ?minimal_fees + ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte ?force + ?max_priority ?(minimal_timestamp = false) ?mempool ?context_path ?src_sk + ~chain ~head delegate = + ( match src_sk with + | None -> + Client_keys.get_key cctxt delegate + >>=? fun (_, _, src_sk) -> return src_sk + | Some sk -> + return sk ) + >>=? fun src_sk -> + Alpha_services.Helpers.current_level cctxt ~offset:1l (chain, head) + >>=? fun level -> + let (seed_nonce, seed_nonce_hash) = + if level.expected_commitment then + let seed_nonce = Client_baking_forge.generate_seed_nonce () in + let seed_nonce_hash = Nonce.hash seed_nonce in + (Some seed_nonce, Some seed_nonce_hash) + else (None, None) + in + let timestamp = + if minimal_timestamp then None + else Some Time.System.(to_protocol (Systime_os.now ())) + in + Client_baking_forge.forge_block + cctxt + ?force + ?minimal_fees + ?minimal_nanotez_per_gas_unit + ?minimal_nanotez_per_byte + ?timestamp + ?seed_nonce_hash + ?mempool + ?context_path + ~chain + ~priority:(`Auto (delegate, max_priority)) + ~delegate_pkh:delegate + ~delegate_sk:src_sk + head + >>=? fun block_hash -> + ( match seed_nonce with + | None -> + return_unit + | Some seed_nonce -> + cctxt#with_lock (fun () -> + let open Client_baking_nonces in + Client_baking_files.resolve_location cctxt ~chain `Nonce + >>=? fun nonces_location -> + load cctxt nonces_location + >>=? fun nonces -> + let nonces = add nonces block_hash seed_nonce in + save cctxt nonces_location nonces) + |> trace_exn (Failure "Error while recording block") ) + >>=? fun () -> + cctxt#message "Injected block %a" Block_hash.pp_short block_hash + >>= fun () -> return_unit + +let endorse_block cctxt ~chain delegate = + Client_keys.get_key cctxt delegate + >>=? fun (_src_name, src_pk, src_sk) -> + Client_baking_endorsement.forge_endorsement + cctxt + ~chain + ~block:cctxt#block + ~src_sk + src_pk + >>=? fun oph -> + cctxt#answer "Operation successfully injected in the node." + >>= fun () -> + cctxt#answer "Operation hash is '%a'." Operation_hash.pp oph + >>= fun () -> return_unit + +let get_predecessor_cycle (cctxt : #Client_context.printer) cycle = + match Cycle.pred cycle with + | None -> + if Cycle.(cycle = root) then + cctxt#error "No predecessor for the first cycle" + else + cctxt#error "Cannot compute the predecessor of cycle %a" Cycle.pp cycle + | Some cycle -> + Lwt.return cycle + +let do_reveal cctxt ~chain ~block nonces = + Client_baking_revelation.inject_seed_nonce_revelation + cctxt + ~chain + ~block + nonces + >>=? fun () -> return_unit + +let reveal_block_nonces (cctxt : #Protocol_client_context.full) ~chain ~block + block_hashes = + cctxt#with_lock (fun () -> + Client_baking_files.resolve_location cctxt ~chain `Nonce + >>=? fun nonces_location -> + Client_baking_nonces.load cctxt nonces_location) + >>=? fun nonces -> + List.filter_map_p + (fun hash -> + Lwt.catch + (fun () -> + Client_baking_blocks.info cctxt (`Hash (hash, 0)) + >>= function + | Ok bi -> Lwt.return_some bi | Error _ -> Lwt.fail Not_found) + (fun _ -> + cctxt#warning + "Cannot find block %a in the chain. (ignoring)@." + Block_hash.pp_short + hash + >>= fun () -> Lwt.return_none)) + block_hashes + >>= fun block_infos -> + List.filter_map_es + (fun (bi : Client_baking_blocks.block_info) -> + match Client_baking_nonces.find_opt nonces bi.hash with + | None -> + cctxt#warning + "Cannot find nonces for block %a (ignoring)@." + Block_hash.pp_short + bi.hash + >>= fun () -> return_none + | Some nonce -> + return_some (bi.hash, (bi.level, nonce))) + block_infos + >>=? fun nonces -> + let nonces = List.map snd nonces in + do_reveal cctxt ~chain ~block nonces + +let reveal_nonces (cctxt : #Protocol_client_context.full) ~chain ~block () = + let open Client_baking_nonces in + cctxt#with_lock (fun () -> + Client_baking_files.resolve_location cctxt ~chain `Nonce + >>=? fun nonces_location -> + load cctxt nonces_location + >>=? fun nonces -> + get_unrevealed_nonces cctxt nonces_location nonces + >>=? fun nonces_to_reveal -> + do_reveal cctxt ~chain ~block nonces_to_reveal + >>=? fun () -> + filter_outdated_nonces cctxt nonces_location nonces + >>=? fun nonces -> + save cctxt nonces_location nonces >>=? fun () -> return_unit) diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_lib.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_lib.mli new file mode 100644 index 0000000000000000000000000000000000000000..dd8e00bf3565bba1dfe20646c50843e47155454b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_lib.mli @@ -0,0 +1,71 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** Mine a block *) +val bake_block : + #Protocol_client_context.full -> + ?minimal_fees:Tez.t -> + ?minimal_nanotez_per_gas_unit:Q.t -> + ?minimal_nanotez_per_byte:Q.t -> + ?force:bool -> + ?max_priority:int -> + ?minimal_timestamp:bool -> + ?mempool:string -> + ?context_path:string -> + ?src_sk:Client_keys.sk_uri -> + chain:Chain_services.chain -> + head:Block_services.block -> + public_key_hash -> + unit tzresult Lwt.t + +(** Endorse a block *) +val endorse_block : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + Client_keys.Public_key_hash.t -> + unit Error_monad.tzresult Lwt.t + +(** Get the previous cycle of the given cycle *) +val get_predecessor_cycle : + #Protocol_client_context.full -> Cycle.t -> Cycle.t Lwt.t + +(** Reveal the nonces used to bake each block in the given list *) +val reveal_block_nonces : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + Block_hash.t list -> + unit Error_monad.tzresult Lwt.t + +(** Reveal all unrevealed nonces *) +val reveal_nonces : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + unit -> + unit Error_monad.tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_nonces.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_nonces.ml new file mode 100644 index 0000000000000000000000000000000000000000..786547e3a8b6d558da6e8b87c2145ede83671166 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_nonces.ml @@ -0,0 +1,194 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +include Internal_event.Legacy_logging.Make_semantic (struct + let name = Protocol.name ^ ".baking.nonces" +end) + +type t = Nonce.t Block_hash.Map.t + +let empty = Block_hash.Map.empty + +let encoding = + let open Data_encoding in + def "seed_nonce" + @@ conv + (fun m -> + Block_hash.Map.fold (fun hash nonce acc -> (hash, nonce) :: acc) m []) + (fun l -> + List.fold_left + (fun map (hash, nonce) -> Block_hash.Map.add hash nonce map) + Block_hash.Map.empty + l) + @@ list (obj2 (req "block" Block_hash.encoding) (req "nonce" Nonce.encoding)) + +let load (wallet : #Client_context.wallet) location = + wallet#load (Client_baking_files.filename location) ~default:empty encoding + +let save (wallet : #Client_context.wallet) location nonces = + wallet#write (Client_baking_files.filename location) nonces encoding + +let mem nonces hash = Block_hash.Map.mem hash nonces + +let find_opt nonces hash = Block_hash.Map.find hash nonces + +let add nonces hash nonce = Block_hash.Map.add hash nonce nonces + +let add_all nonces nonces_to_add = + Block_hash.Map.fold + (fun hash nonce acc -> add acc hash nonce) + nonces_to_add + nonces + +let remove nonces hash = Block_hash.Map.remove hash nonces + +let remove_all nonces nonces_to_remove = + Block_hash.Map.fold + (fun hash _ acc -> remove acc hash) + nonces_to_remove + nonces + +let get_block_level_opt cctxt ~chain ~block = + Shell_services.Blocks.Header.shell_header cctxt ~chain ~block () + >>= function + | Ok {level; _} -> + Lwt.return_some level + | Error errs -> + lwt_warn + Tag.DSL.( + fun f -> + f + "@[Cannot retrieve block %a header associated to nonce:@ \ + @[%a@]@]@." + -% t event "cannot_retrieve_block_header" + -% a Logging.block_tag block -% a errs_tag errs) + >>= fun () -> Lwt.return_none + +let get_outdated_nonces cctxt ?constants ~chain nonces = + ( match constants with + | None -> + Alpha_services.Constants.all cctxt (chain, `Head 0) + | Some constants -> + return constants ) + >>=? fun {Constants.parametric = {blocks_per_cycle; preserved_cycles; _}; _} -> + get_block_level_opt cctxt ~chain ~block:(`Head 0) + >>= function + | None -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Cannot fetch chain's head level. Aborting nonces filtering." + -% t event "cannot_retrieve_head_level") + >>= fun () -> return (empty, empty) + | Some current_level -> + let current_cycle = Int32.(div current_level blocks_per_cycle) in + let is_older_than_preserved_cycles block_level = + let block_cycle = Int32.(div block_level blocks_per_cycle) in + Int32.sub current_cycle block_cycle > Int32.of_int preserved_cycles + in + Block_hash.Map.fold + (fun hash nonce acc -> + acc + >>=? fun (orphans, outdated) -> + get_block_level_opt cctxt ~chain ~block:(`Hash (hash, 0)) + >>= function + | Some level -> + if is_older_than_preserved_cycles level then + return (orphans, add outdated hash nonce) + else acc + | None -> + return (add orphans hash nonce, outdated)) + nonces + (return (empty, empty)) + +let filter_outdated_nonces cctxt ?constants location nonces = + let chain = Client_baking_files.chain location in + get_outdated_nonces cctxt ?constants ~chain nonces + >>=? fun (orphans, outdated_nonces) -> + ( if Block_hash.Map.cardinal orphans >= 50 then + lwt_warn + Tag.DSL.( + fun f -> + f + "Found too many nonces associated to blocks unknown by the node \ + in '$TEZOS_CLIENT/%s'. After checking that these blocks were \ + never included in the chain (e.g. via a block explorer), \ + consider using `tezos-client filter orphan nonces` to clear them." + -% s + Logging.filename_tag + (Client_baking_files.filename location ^ "s") + -% t event "too_many_orphans") + >>= fun () -> Lwt.return_unit + else Lwt.return_unit ) + >>= fun () -> return (remove_all nonces outdated_nonces) + +let get_unrevealed_nonces cctxt location nonces = + let chain = Client_baking_files.chain location in + Client_baking_blocks.blocks_from_current_cycle + cctxt + ~chain + (`Head 0) + ~offset:(-1l) + () + >>=? fun blocks -> + List.filter_map_es + (fun hash -> + match find_opt nonces hash with + | None -> + return_none + | Some nonce -> ( + get_block_level_opt cctxt ~chain ~block:(`Hash (hash, 0)) + >>= function + | Some level -> ( + Environment.wrap_tzresult (Raw_level.of_int32 level) + >>?= fun level -> + Alpha_services.Nonce.get cctxt (chain, `Head 0) level + >>=? function + | Missing nonce_hash when Nonce.check_hash nonce nonce_hash -> + lwt_log_notice + Tag.DSL.( + fun f -> + f "Found nonce to reveal for %a (level: %a)" + -% t event "found_nonce" + -% a Block_hash.Logging.tag hash + -% a Logging.level_tag level) + >>= fun () -> return_some (level, nonce) + | Missing _nonce_hash -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Incoherent nonce for level %a" + -% t event "bad_nonce" -% a Logging.level_tag level) + >>= fun () -> return_none + | Forgotten -> + return_none + | Revealed _ -> + return_none ) + | None -> + return_none )) + blocks diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_nonces.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_nonces.mli new file mode 100644 index 0000000000000000000000000000000000000000..b5c18d3b6a681f5bde092c3c992eaea74d4dae98 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_nonces.mli @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = Nonce.t Block_hash.Map.t + +val encoding : t Data_encoding.t + +val empty : t + +val load : + #Client_context.wallet -> + [`Nonce] Client_baking_files.location -> + t tzresult Lwt.t + +val save : + #Client_context.wallet -> + [`Nonce] Client_baking_files.location -> + t -> + unit tzresult Lwt.t + +val mem : t -> Block_hash.t -> bool + +val find_opt : t -> Block_hash.t -> Nonce.t option + +val add : t -> Block_hash.t -> Nonce.t -> t + +val add_all : t -> t -> t + +val remove : t -> Block_hash.t -> t + +val remove_all : t -> t -> t + +(** [get_outdated_nonces] returns the nonces that cannot be associated + to blocks (orphans) and the nonces that are older than 5 cycles. *) +val get_outdated_nonces : + #Protocol_client_context.full -> + ?constants:Constants.t -> + chain:Block_services.chain -> + t -> + (t * t) tzresult Lwt.t + +(** [filter_outdated_nonces] filters nonces older than 5 cycles in the + nonce file. *) +val filter_outdated_nonces : + #Protocol_client_context.full -> + ?constants:Constants.t -> + [`Nonce] Client_baking_files.location -> + t -> + t tzresult Lwt.t + +(** [get_unrevealed_nonces] retrieve registered nonces *) +val get_unrevealed_nonces : + #Protocol_client_context.full -> + [`Nonce] Client_baking_files.location -> + t -> + (Raw_level.t * Nonce.t) list tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_pow.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_pow.ml new file mode 100644 index 0000000000000000000000000000000000000000..f7130f9d7af8786ec83224a23c453ddbb8784fe0 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_pow.ml @@ -0,0 +1,83 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +let default_constant = "\x00\x00\x00\x05" + +let is_updated_constant = + let commit_hash = + if TzString.is_hex Tezos_version.Current_git_info.commit_hash then + Hex.to_string (`Hex Tezos_version.Current_git_info.commit_hash) + else Tezos_version.Current_git_info.commit_hash + in + if String.length commit_hash >= 4 then String.sub commit_hash 0 4 + else default_constant + +let is_updated_constant_len = String.length is_updated_constant + +(* add a version to the pow *) +let init_proof_of_work_nonce () = + let buf = + Bytes.make Alpha_context.Constants.proof_of_work_nonce_size '\000' + in + Bytes.blit_string is_updated_constant 0 buf 0 is_updated_constant_len ; + let max_z_len = + Alpha_context.Constants.proof_of_work_nonce_size - is_updated_constant_len + in + let rec aux z = + let z_len = (Z.numbits z + 7) / 8 in + if z_len > max_z_len then Seq.Nil + else ( + Bytes.blit_string (Z.to_bits z) 0 buf is_updated_constant_len z_len ; + Seq.Cons (buf, fun () -> aux (Z.succ z)) ) + in + aux Z.zero + +(* This was used before November 2018 *) +(* (\* Random proof of work *\) + * let generate_proof_of_work_nonce () = + * Rand.generate Alpha_context.Constants.proof_of_work_nonce_size *) + +let empty_proof_of_work_nonce = + Bytes.make Constants_repr.proof_of_work_nonce_size '\000' + +let mine cctxt chain block shell builder = + Alpha_services.Constants.all cctxt (chain, block) + >>=? fun constants -> + let threshold = constants.parametric.proof_of_work_threshold in + let rec loop nonce_seq = + match nonce_seq with + | Seq.Nil -> + failwith + "Client_baking_pow.mine: couldn't find nonce for required proof of \ + work" + | Seq.Cons (nonce, seq) -> + let block = builder nonce in + if Baking.check_header_proof_of_work_stamp shell block threshold then + return block + else loop (seq ()) + in + loop (init_proof_of_work_nonce ()) diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_pow.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_pow.mli new file mode 100644 index 0000000000000000000000000000000000000000..f61d37970ba27aa9808d7a9d46b0bf7d3f7226f6 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_pow.mli @@ -0,0 +1,42 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** A null proof-of-work nonce. This should only be used to nonsensical blocks + of the correct size and shape. *) +val empty_proof_of_work_nonce : Bytes.t + +(** [mine cctxt chain block header builder] returns a block with a valid + proof-of-work nonce. The function [builder], provided by the caller, is used + to make the block. All the internal logic of generating nonces and checking + for the proof-of-work threshold is handled by [mine]. *) +val mine : + #Protocol_client_context.full -> + Shell_services.chain -> + Block_services.block -> + Block_header.shell_header -> + (Bytes.t -> Alpha_context.Block_header.contents) -> + Alpha_context.Block_header.contents tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_revelation.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_revelation.ml new file mode 100644 index 0000000000000000000000000000000000000000..6aa5d9bc9a8ad3a710fbb27b0b0624ea8beaaf06 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_revelation.ml @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +include Internal_event.Legacy_logging.Make_semantic (struct + let name = Protocol.name ^ ".baking.nonce_revelation" +end) + +let inject_seed_nonce_revelation (cctxt : #Protocol_client_context.full) ~chain + ~block ?async nonces = + Shell_services.Blocks.hash cctxt ~chain ~block () + >>=? fun hash -> + match nonces with + | [] -> + lwt_log_notice + Tag.DSL.( + fun f -> + f "Nothing to reveal for block %a" + -% t event "no_nonce_reveal" + -% a Block_hash.Logging.tag hash) + >>= fun () -> return_unit + | _ -> + List.iter_es + (fun (level, nonce) -> + Alpha_services.Forge.seed_nonce_revelation + cctxt + (chain, block) + ~branch:hash + ~level + ~nonce + () + >>=? fun bytes -> + let bytes = Signature.concat bytes Signature.zero in + Shell_services.Injection.operation cctxt ?async ~chain bytes + >>=? fun oph -> + lwt_log_notice + Tag.DSL.( + fun f -> + f + "Revealing nonce %a from level %a for chain %a, block %a \ + with operation %a" + -% t event "reveal_nonce" -% a Logging.nonce_tag nonce + -% a Logging.level_tag level -% a Logging.chain_tag chain + -% a Logging.block_tag block + -% a Operation_hash.Logging.tag oph) + >>= fun () -> return_unit) + nonces diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_revelation.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_revelation.mli new file mode 100644 index 0000000000000000000000000000000000000000..f13532831a9a852e6e52a6cd2e6fcd21280efb82 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_revelation.mli @@ -0,0 +1,35 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +val inject_seed_nonce_revelation : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?async:bool -> + (Raw_level.t * Nonce.t) list -> + unit tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_scheduling.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_scheduling.ml new file mode 100644 index 0000000000000000000000000000000000000000..547914b35e337ca1cc78542758bf53d4de4d857e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_scheduling.ml @@ -0,0 +1,166 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Internal_event.Legacy_logging.Make_semantic (struct + let name = Protocol.name ^ ".baking.scheduling" +end) + +open Logging +open Protocol_client_context + +type error += Node_connection_lost + +let () = + register_error_kind + `Temporary + ~id:"client_baking_scheduling.node_connection_lost" + ~title:"Node connection lost" + ~description:"The connection with the node was lost." + ~pp:(fun fmt () -> Format.fprintf fmt "Lost connection with the node") + Data_encoding.empty + (function Node_connection_lost -> Some () | _ -> None) + (fun () -> Node_connection_lost) + +let sleep_until time = + (* Sleeping is a system op, baking is a protocol op, this is where we convert *) + let time = Time.System.of_protocol_exn time in + let delay = Ptime.diff time (Tezos_stdlib_unix.Systime_os.now ()) in + if Ptime.Span.compare delay Ptime.Span.zero < 0 then None + else Some (Lwt_unix.sleep (Ptime.Span.to_float_s delay)) + +let rec wait_for_first_event ~name stream = + Lwt_stream.get stream + >>= function + | None | Some (Error _) -> + lwt_log_info + Tag.DSL.( + fun f -> + f "Can't fetch the current event. Waiting for new event." + -% t event "cannot_fetch_event" + -% t worker_tag name) + >>= fun () -> + (* NOTE: this is not a tight loop because of Lwt_stream.get *) + wait_for_first_event ~name stream + | Some (Ok bi) -> + Lwt.return bi + +let log_errors_and_continue ~name p = + p + >>= function + | Ok () -> + Lwt.return_unit + | Error errs -> + lwt_log_error + Tag.DSL.( + fun f -> + f "Error while baking:@\n%a" + -% t event "daemon_error" -% t worker_tag name -% a errs_tag errs) + +let main ~(name : string) ~(cctxt : #Protocol_client_context.full) + ~(stream : 'event tzresult Lwt_stream.t) + ~(state_maker : 'event -> 'state tzresult Lwt.t) + ~(pre_loop : + #Protocol_client_context.full -> 'state -> 'event -> unit tzresult Lwt.t) + ~(compute_timeout : 'state -> 'timesup Lwt.t) + ~(timeout_k : + #Protocol_client_context.full -> + 'state -> + 'timesup -> + unit tzresult Lwt.t) + ~(event_k : + #Protocol_client_context.full -> 'state -> 'event -> unit tzresult Lwt.t) + ~finalizer = + lwt_log_info + Tag.DSL.( + fun f -> + f "Setting up before the %s can start." + -% t event "daemon_setup" -% s worker_tag name) + >>= fun () -> + wait_for_first_event ~name stream + >>= fun first_event -> + (* statefulness *) + let last_get_event = ref None in + let get_event () = + match !last_get_event with + | None -> + let t = Lwt_stream.get stream in + last_get_event := Some t ; + t + | Some t -> + t + in + state_maker first_event + >>=? fun state -> + (* main loop *) + let rec worker_loop () = + (* event construction *) + let timeout = compute_timeout state in + Lwt.choose + [ (Lwt_exit.clean_up_starts >|= fun _ -> `Termination); + (timeout >|= fun timesup -> `Timeout timesup); + (get_event () >|= fun e -> `Event e) ] + >>= function + (* event matching *) + | `Termination -> + return_unit + | `Event (None | Some (Error _)) -> + (* exit when the node is unavailable *) + last_get_event := None ; + lwt_log_error + Tag.DSL.( + fun f -> + f "Connection to node lost, %s exiting." + -% t event "daemon_connection_lost" + -% s worker_tag name) + >>= fun () -> fail Node_connection_lost + | `Event (Some (Ok event)) -> + (* new event: cancel everything and execute callback *) + last_get_event := None ; + (* TODO: pretty-print events (requires passing a pp as argument) *) + log_errors_and_continue ~name @@ event_k cctxt state event + >>= fun () -> worker_loop () + | `Timeout timesup -> + (* main event: it's time *) + lwt_debug + Tag.DSL.( + fun f -> + f "Waking up for %s." -% t event "daemon_wakeup" + -% s worker_tag name) + >>= fun () -> + (* core functionality *) + log_errors_and_continue ~name @@ timeout_k cctxt state timesup + >>= fun () -> worker_loop () + in + (* ignition *) + lwt_log_info + Tag.DSL.( + fun f -> + f "Starting %s daemon" -% t event "daemon_start" -% s worker_tag name) + >>= fun () -> + Lwt.finalize + (fun () -> + log_errors_and_continue ~name @@ pre_loop cctxt state first_event + >>= fun () -> worker_loop ()) + (fun () -> finalizer state) diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_scheduling.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_scheduling.mli new file mode 100644 index 0000000000000000000000000000000000000000..ba8494f2d13515864c7223a90cca99166c4e9cd8 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_scheduling.mli @@ -0,0 +1,56 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Node_connection_lost + +val sleep_until : Time.Protocol.t -> unit Lwt.t option + +val wait_for_first_event : + name:string -> 'event tzresult Lwt_stream.t -> 'event Lwt.t + +val main : + name:string -> + cctxt:(#Protocol_client_context.full as 'a) -> + stream:'event tzresult Lwt_stream.t -> + state_maker:('event -> 'state tzresult Lwt.t) -> + pre_loop:('a -> 'state -> 'event -> unit tzresult Lwt.t) -> + compute_timeout:('state -> 'timesup Lwt.t) -> + timeout_k:('a -> 'state -> 'timesup -> unit tzresult Lwt.t) -> + event_k:('a -> 'state -> 'event -> unit tzresult Lwt.t) -> + finalizer:('state -> unit Lwt.t) -> + unit tzresult Lwt.t + +(** [main ~name ~cctxt ~stream ~state_maker ~pre_loop ~timeout_maker ~timeout_k + ~event_k] is an infinitely running loop that + monitors new events arriving on [stream]. The loop exits when the + [stream] gives an error. + + The function [pre_loop] is called before the loop starts. + + The loop maintains a state (of type ['state]) initialized by [state_maker] + and passed to the callbacks [timeout_maker] (used to set up waking-up + timeouts), [timeout_k] (when a computed timeout happens), and [event_k] + (when a new event arrives on the stream). +*) diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_simulator.ml b/src/proto_009_PsFLoren/lib_delegate/client_baking_simulator.ml new file mode 100644 index 0000000000000000000000000000000000000000..0c22878135b6acf00190c4b922723ecc674e8112 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_simulator.ml @@ -0,0 +1,116 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Protocol +open Alpha_context + +type error += Failed_to_checkout_context + +type error += Invalid_context + +let ( >>=?? ) x k = + x >>= fun x -> Lwt.return (Environment.wrap_tzresult x) >>=? k + +let () = + register_error_kind + `Permanent + ~id:"Client_baking_simulator.failed_to_checkout_context" + ~title:"Failed to checkout context" + ~description:"The given context hash does not exists in the context." + ~pp:(fun ppf () -> Format.fprintf ppf "Failed to checkout the context") + Data_encoding.unit + (function Failed_to_checkout_context -> Some () | _ -> None) + (fun () -> Failed_to_checkout_context) ; + register_error_kind + `Permanent + ~id:"Client_baking_simulator.invalid_context" + ~title:"Invalid context" + ~description:"Occurs when the context is inconsistent." + ~pp:(fun ppf () -> Format.fprintf ppf "The given context is invalid.") + Data_encoding.unit + (function Invalid_context -> Some () | _ -> None) + (fun () -> Invalid_context) + +type incremental = { + predecessor : Client_baking_blocks.block_info; + context : Tezos_protocol_environment.Context.t; + state : Protocol.validation_state; + rev_operations : Operation.packed list; + header : Tezos_base.Block_header.shell_header; +} + +let load_context ~context_path = Context.init ~readonly:true context_path + +let check_context_consistency index context_hash = + (* Hypothesis : the version key exists *) + let version_key = ["version"] in + Context.checkout index context_hash + >>= function + | None -> + fail Failed_to_checkout_context + | Some context -> ( + Context.mem context version_key + >>= function true -> return_unit | false -> fail Invalid_context ) + +let begin_construction ~timestamp ?protocol_data index predecessor = + let {Client_baking_blocks.context; _} = predecessor in + Shell_context.checkout index context + >>= function + | None -> + fail Failed_to_checkout_context + | Some context -> + let header : Tezos_base.Block_header.shell_header = + Tezos_base.Block_header. + { + predecessor = predecessor.hash; + proto_level = predecessor.proto_level; + validation_passes = 0; + fitness = predecessor.fitness; + timestamp; + level = Raw_level.to_int32 predecessor.level; + context = Context_hash.zero; + operations_hash = Operation_list_list_hash.zero; + } + in + Protocol.begin_construction + ~chain_id:predecessor.chain_id + ~predecessor_context:context + ~predecessor_timestamp:predecessor.timestamp + ~predecessor_fitness:predecessor.fitness + ~predecessor_level:(Raw_level.to_int32 predecessor.level) + ~predecessor:predecessor.hash + ?protocol_data + ~timestamp + () + >>=?? fun state -> + return {predecessor; context; state; rev_operations = []; header} + +let add_operation st (op : Operation.packed) = + Protocol.apply_operation st.state op + >>=?? fun (state, receipt) -> + return ({st with state; rev_operations = op :: st.rev_operations}, receipt) + +let finalize_construction inc = Protocol.finalize_block inc.state >>=?? return diff --git a/src/proto_009_PsFLoren/lib_delegate/client_baking_simulator.mli b/src/proto_009_PsFLoren/lib_delegate/client_baking_simulator.mli new file mode 100644 index 0000000000000000000000000000000000000000..912adb99f9d0333302a0987de5c15a42ae2945b1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_baking_simulator.mli @@ -0,0 +1,59 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type incremental = { + predecessor : Client_baking_blocks.block_info; + context : Tezos_protocol_environment.Context.t; + state : validation_state; + rev_operations : Operation.packed list; + header : Tezos_base.Block_header.shell_header; +} + +val load_context : context_path:string -> Context.index Lwt.t + +(** Make sure that the given context is consistent by trying to read in it *) +val check_context_consistency : + Context.index -> Context_hash.t -> unit tzresult Lwt.t + +val begin_construction : + timestamp:Time.Protocol.t -> + ?protocol_data:block_header_data -> + Context.index -> + Client_baking_blocks.block_info -> + incremental tzresult Lwt.t + +val add_operation : + incremental -> + Operation.packed -> + (incremental * operation_receipt) tzresult Lwt.t + +val finalize_construction : + incremental -> + (Tezos_protocol_environment.validation_result * block_header_metadata) + tzresult + Lwt.t diff --git a/src/proto_009_PsFLoren/lib_delegate/client_daemon.ml b/src/proto_009_PsFLoren/lib_delegate/client_daemon.ml new file mode 100644 index 0000000000000000000000000000000000000000..ba93851711876f242c92e83b61437bd3f00517b2 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_daemon.ml @@ -0,0 +1,149 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let rec retry (cctxt : #Protocol_client_context.full) ?max_delay ~delay ~factor + ~tries f x = + f x + >>= function + | Ok _ as r -> + Lwt.return r + | Error + (RPC_client_errors.Request_failed {error = Connection_failed _; _} :: _) + as err + when tries > 0 -> ( + cctxt#message "Connection refused, retrying in %.2f seconds..." delay + >>= fun () -> + Lwt.pick + [ (Lwt_unix.sleep delay >|= fun () -> `Continue); + (Lwt_exit.clean_up_starts >|= fun _ -> `Killed) ] + >>= function + | `Killed -> + Lwt.return err + | `Continue -> + let next_delay = delay *. factor in + let delay = + Option.fold + ~none:next_delay + ~some:(fun max_delay -> Float.min next_delay max_delay) + max_delay + in + retry cctxt ?max_delay ~delay ~factor ~tries:(tries - 1) f x ) + | Error _ as err -> + Lwt.return err + +let rec retry_on_disconnection (cctxt : #Protocol_client_context.full) f = + f () + >>= function + | Ok () -> + return_unit + | Error (Client_baking_scheduling.Node_connection_lost :: _) -> + cctxt#warning + "Lost connection with the node. Retrying to establish connection..." + >>= fun () -> + (* Wait forever when the node stops responding... *) + Client_confirmations.wait_for_bootstrapped + ~retry: + (retry cctxt ~max_delay:10. ~delay:1. ~factor:1.5 ~tries:max_int) + cctxt + >>=? fun () -> retry_on_disconnection cctxt f + | Error err -> + cctxt#error "Unexpected error: %a. Exiting..." pp_print_error err + +module Endorser = struct + let run (cctxt : #Protocol_client_context.full) ~chain ~delay ~keep_alive + delegates = + let process () = + Client_baking_blocks.monitor_heads + ~next_protocols:(Some [Protocol.hash]) + cctxt + chain + >>=? fun block_stream -> + cctxt#message "Endorser started." + >>= fun () -> + Client_baking_endorsement.create cctxt ~delay delegates block_stream + in + Client_confirmations.wait_for_bootstrapped + ~retry:(retry cctxt ~delay:1. ~factor:1.5 ~tries:5) + cctxt + >>=? fun () -> + if keep_alive then retry_on_disconnection cctxt process else process () +end + +module Baker = struct + let run (cctxt : #Protocol_client_context.full) ?minimal_fees + ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte ?max_priority + ~chain ~context_path ~keep_alive delegates = + let process () = + Config_services.user_activated_upgrades cctxt + >>=? fun user_activated_upgrades -> + Client_baking_blocks.monitor_heads + ~next_protocols:(Some [Protocol.hash]) + cctxt + chain + >>=? fun block_stream -> + cctxt#message "Baker started." + >>= fun () -> + Client_baking_forge.create + cctxt + ~user_activated_upgrades + ?minimal_fees + ?minimal_nanotez_per_gas_unit + ?minimal_nanotez_per_byte + ?max_priority + ~chain + ~context_path + delegates + block_stream + in + Client_confirmations.wait_for_bootstrapped + ~retry:(retry cctxt ~delay:1. ~factor:1.5 ~tries:5) + cctxt + >>=? fun () -> + if keep_alive then retry_on_disconnection cctxt process else process () +end + +module Accuser = struct + let run (cctxt : #Protocol_client_context.full) ~chain ~preserved_levels + ~keep_alive = + let process () = + Client_baking_blocks.monitor_valid_blocks + ~next_protocols:(Some [Protocol.hash]) + cctxt + ~chains:[chain] + () + >>=? fun valid_blocks_stream -> + cctxt#message "Accuser started." + >>= fun () -> + Client_baking_denunciation.create + cctxt + ~preserved_levels + valid_blocks_stream + in + Client_confirmations.wait_for_bootstrapped + ~retry:(retry cctxt ~delay:1. ~factor:1.5 ~tries:5) + cctxt + >>=? fun () -> + if keep_alive then retry_on_disconnection cctxt process else process () +end diff --git a/src/proto_009_PsFLoren/lib_delegate/client_daemon.mli b/src/proto_009_PsFLoren/lib_delegate/client_daemon.mli new file mode 100644 index 0000000000000000000000000000000000000000..410e71670ec9261f31e46671b30711739bfc6007 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/client_daemon.mli @@ -0,0 +1,60 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module Endorser : sig + val run : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + delay:int -> + keep_alive:bool -> + public_key_hash list -> + unit tzresult Lwt.t +end + +module Baker : sig + val run : + #Protocol_client_context.full -> + ?minimal_fees:Tez.t -> + ?minimal_nanotez_per_gas_unit:Q.t -> + ?minimal_nanotez_per_byte:Q.t -> + ?max_priority:int -> + chain:Chain_services.chain -> + context_path:string -> + keep_alive:bool -> + public_key_hash list -> + unit tzresult Lwt.t +end + +module Accuser : sig + val run : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + preserved_levels:int -> + keep_alive:bool -> + unit tzresult Lwt.t +end diff --git a/src/proto_009_PsFLoren/lib_delegate/delegate_commands.ml b/src/proto_009_PsFLoren/lib_delegate/delegate_commands.ml new file mode 100644 index 0000000000000000000000000000000000000000..f7bcf06e678c020aa3dfc3693719e79dae202f2d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/delegate_commands.ml @@ -0,0 +1,346 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Client_proto_args +open Client_baking_lib + +let group = + {Clic.name = "delegate"; title = "Commands related to delegate operations."} + +let directory_parameter = + Clic.parameter (fun _ p -> + if not (Sys.file_exists p && Sys.is_directory p) then + failwith "Directory doesn't exist: '%s'" p + else return p) + +let mempool_arg = + Clic.arg + ~long:"mempool" + ~placeholder:"file" + ~doc: + "When used the client will read the mempool in the provided file \ + instead of querying the node through an RPC (useful for debugging \ + only)." + string_parameter + +let context_path_arg = + Clic.arg + ~long:"context" + ~placeholder:"path" + ~doc: + "When use the client will read in the local context at the provided \ + path in order to build the block, instead of relying on the 'preapply' \ + RPC." + string_parameter + +let pidfile_arg = + Clic.arg + ~doc:"write process id in file" + ~short:'P' + ~long:"pidfile" + ~placeholder:"filename" + (Clic.parameter (fun _ s -> return s)) + +let may_lock_pidfile = function + | None -> + return_unit + | Some pidfile -> + trace (failure "Failed to create the pidfile: %s" pidfile) + @@ Lwt_lock_file.create ~unlink_on_exit:true pidfile + +let block_param t = + Clic.param + ~name:"block" + ~desc:"commitment blocks whose nonce should be revealed" + (Clic.parameter (fun _ str -> Lwt.return (Block_hash.of_b58check str))) + t + +let keep_alive_arg = + Clic.switch + ~doc: + "Keep the daemon process alive: when the connection with the node is \ + lost, the daemon periodically tries to reach it." + ~short:'K' + ~long:"keep-alive" + () + +let delegate_commands () = + let open Clic in + [ command + ~group + ~desc:"Forge and inject block using the delegate rights." + (args8 + max_priority_arg + minimal_fees_arg + minimal_nanotez_per_gas_unit_arg + minimal_nanotez_per_byte_arg + force_switch + minimal_timestamp_switch + mempool_arg + context_path_arg) + ( prefixes ["bake"; "for"] + @@ Client_keys.Public_key_hash.source_param + ~name:"baker" + ~desc:"name of the delegate owning the baking right" + @@ stop ) + (fun ( max_priority, + minimal_fees, + minimal_nanotez_per_gas_unit, + minimal_nanotez_per_byte, + force, + minimal_timestamp, + mempool, + context_path ) + delegate + cctxt -> + bake_block + cctxt + ~minimal_fees + ~minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte + ~force + ?max_priority + ~minimal_timestamp + ?mempool + ?context_path + ~chain:cctxt#chain + ~head:cctxt#block + delegate); + command + ~group + ~desc:"Forge and inject a seed-nonce revelation operation." + no_options + (prefixes ["reveal"; "nonce"; "for"] @@ seq_of_param block_param) + (fun () block_hashes cctxt -> + reveal_block_nonces + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + block_hashes); + command + ~group + ~desc: + "Forge and inject all the possible seed-nonce revelation operations." + no_options + (prefixes ["reveal"; "nonces"] @@ stop) + (fun () cctxt -> + reveal_nonces ~chain:cctxt#chain ~block:cctxt#block cctxt ()); + command + ~group + ~desc:"Forge and inject an endorsement operation." + no_options + ( prefixes ["endorse"; "for"] + @@ Client_keys.Public_key_hash.source_param + ~name:"baker" + ~desc:"name of the delegate owning the endorsement right" + @@ stop ) + (fun () delegate cctxt -> + endorse_block cctxt ~chain:cctxt#chain delegate); + command + ~group + ~desc: + "Clear the nonces file by removing the nonces which blocks cannot be \ + found on the chain." + no_options + (prefixes ["filter"; "orphan"; "nonces"] @@ stop) + (fun () (cctxt : #Protocol_client_context.full) -> + cctxt#with_lock (fun () -> + let chain = cctxt#chain in + Client_baking_files.resolve_location cctxt ~chain `Nonce + >>=? fun nonces_location -> + let open Client_baking_nonces in + (* Filtering orphan nonces *) + load cctxt nonces_location + >>=? fun nonces -> + Block_hash.Map.fold + (fun block nonce acc -> + acc + >>= fun acc -> + Shell_services.Blocks.Header.shell_header + cctxt + ~chain + ~block:(`Hash (block, 0)) + () + >>= function + | Ok _ -> + Lwt.return acc + | Error _ -> + Lwt.return (Block_hash.Map.add block nonce acc)) + nonces + (Lwt.return empty) + >>= fun orphans -> + if Block_hash.Map.cardinal orphans = 0 then + cctxt#message "No orphan nonces found." >>= fun () -> return_unit + else + (* "Backup-ing" orphan nonces *) + let orphan_nonces_file = "orphan_nonce" in + cctxt#load orphan_nonces_file ~default:empty encoding + >>=? fun orphan_nonces -> + let orphan_nonces = add_all orphan_nonces orphans in + cctxt#write orphan_nonces_file orphan_nonces encoding + >>=? fun () -> + (* Don't forget the 's'. *) + let orphan_nonces_file = orphan_nonces_file ^ "s" in + cctxt#message + "Successfully filtered %d orphan nonces and moved them to \ + '$TEZOS_CLIENT/%s'." + (Block_hash.Map.cardinal orphans) + orphan_nonces_file + >>= fun () -> + let filtered_nonces = + Client_baking_nonces.remove_all nonces orphans + in + save cctxt nonces_location filtered_nonces + >>=? fun () -> return_unit)); + command + ~group + ~desc:"List orphan nonces." + no_options + (prefixes ["list"; "orphan"; "nonces"] @@ stop) + (fun () (cctxt : #Protocol_client_context.full) -> + cctxt#with_lock (fun () -> + let open Client_baking_nonces in + let orphan_nonces_file = "orphan_nonce" in + cctxt#load orphan_nonces_file ~default:empty encoding + >>=? fun orphan_nonces -> + let block_hashes = + List.map fst (Block_hash.Map.bindings orphan_nonces) + in + cctxt#message + "@[Found %d orphan nonces associated to the potentially \ + unknown following blocks:@ %a@]" + (Block_hash.Map.cardinal orphan_nonces) + (Format.pp_print_list ~pp_sep:Format.pp_print_cut Block_hash.pp) + block_hashes + >>= fun () -> return_unit)) ] + +let baker_commands () = + let open Clic in + let group = + { + Clic.name = "delegate.baker"; + title = "Commands related to the baker daemon."; + } + in + [ command + ~group + ~desc:"Launch the baker daemon." + (args6 + pidfile_arg + max_priority_arg + minimal_fees_arg + minimal_nanotez_per_gas_unit_arg + minimal_nanotez_per_byte_arg + keep_alive_arg) + ( prefixes ["run"; "with"; "local"; "node"] + @@ param + ~name:"context_path" + ~desc:"Path to the node data directory (e.g. $HOME/.tezos-node)" + directory_parameter + @@ seq_of_param Client_keys.Public_key_hash.alias_param ) + (fun ( pidfile, + max_priority, + minimal_fees, + minimal_nanotez_per_gas_unit, + minimal_nanotez_per_byte, + keep_alive ) + node_path + delegates + cctxt -> + may_lock_pidfile pidfile + >>=? fun () -> + Tezos_signer_backends.Encrypted.decrypt_list + cctxt + (List.map fst delegates) + >>=? fun () -> + Client_daemon.Baker.run + cctxt + ~chain:cctxt#chain + ~minimal_fees + ~minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte + ?max_priority + ~context_path:(Filename.concat node_path "context") + ~keep_alive + (List.map snd delegates)) ] + +let endorser_commands () = + let open Clic in + let group = + { + Clic.name = "delegate.endorser"; + title = "Commands related to endorser daemon."; + } + in + [ command + ~group + ~desc:"Launch the endorser daemon" + (args3 pidfile_arg endorsement_delay_arg keep_alive_arg) + (prefixes ["run"] @@ seq_of_param Client_keys.Public_key_hash.alias_param) + (fun (pidfile, endorsement_delay, keep_alive) delegates cctxt -> + may_lock_pidfile pidfile + >>=? fun () -> + Tezos_signer_backends.Encrypted.decrypt_list + cctxt + (List.map fst delegates) + >>=? fun () -> + let delegates = List.map snd delegates in + let delegates_no_duplicates = + Signature.Public_key_hash.Set.(delegates |> of_list |> elements) + in + ( if List.length delegates <> List.length delegates_no_duplicates then + cctxt#message + "Warning: the list of public key hash aliases contains duplicate \ + hashes, which are ignored" + else Lwt.return () ) + >>= fun () -> + Client_daemon.Endorser.run + cctxt + ~chain:cctxt#chain + ~delay:endorsement_delay + ~keep_alive + delegates_no_duplicates) ] + +let accuser_commands () = + let open Clic in + let group = + { + Clic.name = "delegate.accuser"; + title = "Commands related to the accuser daemon."; + } + in + [ command + ~group + ~desc:"Launch the accuser daemon" + (args3 pidfile_arg preserved_levels_arg keep_alive_arg) + (prefixes ["run"] @@ stop) + (fun (pidfile, preserved_levels, keep_alive) cctxt -> + may_lock_pidfile pidfile + >>=? fun () -> + Client_daemon.Accuser.run + cctxt + ~chain:cctxt#chain + ~preserved_levels + ~keep_alive) ] diff --git a/src/proto_009_PsFLoren/lib_delegate/delegate_commands.mli b/src/proto_009_PsFLoren/lib_delegate/delegate_commands.mli new file mode 100644 index 0000000000000000000000000000000000000000..0bf46215dce0efd8758a2c40276b28f48d1f8355 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/delegate_commands.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val delegate_commands : unit -> Protocol_client_context.full Clic.command list + +val baker_commands : unit -> Protocol_client_context.full Clic.command list + +val endorser_commands : unit -> Protocol_client_context.full Clic.command list + +val accuser_commands : unit -> Protocol_client_context.full Clic.command list diff --git a/src/proto_009_PsFLoren/lib_delegate/delegate_commands_registration.ml b/src/proto_009_PsFLoren/lib_delegate/delegate_commands_registration.ml new file mode 100644 index 0000000000000000000000000000000000000000..1046b7fe5200ecc550ee7dc5de55887ea4ebb2de --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/delegate_commands_registration.ml @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = + Client_commands.register Protocol.hash + @@ fun _network -> + List.map (Clic.map_command (new Protocol_client_context.wrap_full)) + @@ Delegate_commands.delegate_commands () diff --git a/src/proto_009_PsFLoren/lib_delegate/dune b/src/proto_009_PsFLoren/lib_delegate/dune new file mode 100644 index 0000000000000000000000000000000000000000..90a1bf131c930b1ca65ca5f0dcfec03f3a093e5c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/dune @@ -0,0 +1,86 @@ +(library + (name tezos_baking_009_PsFLoren) + (public_name tezos-baking-009-PsFLoren) + (libraries tezos-base + tezos-version + tezos-protocol-009-PsFLoren + tezos-protocol-environment + tezos-shell-context + tezos-shell-services + tezos-client-base + tezos-client-009-PsFLoren + tezos-client-commands + tezos-stdlib-unix + tezos-storage + tezos-rpc-http + tezos-rpc + lwt-canceler + lwt-exit) + (library_flags (:standard -linkall)) + (modules (:standard \ + delegate_commands + delegate_commands_registration)) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_009_PsFLoren + -open Tezos_client_commands + -open Tezos_stdlib_unix + -open Tezos_shell_context + -open Tezos_storage + -open Tezos_rpc + -open Tezos_rpc_http))) + +(library + (name tezos_baking_009_PsFLoren_commands) + (public_name tezos-baking-009-PsFLoren-commands) + (libraries tezos-base + tezos-protocol-009-PsFLoren + tezos-protocol-environment + tezos-shell-services + tezos-client-base + tezos-client-009-PsFLoren + tezos-client-commands + tezos-baking-009-PsFLoren) + (library_flags (:standard -linkall)) + (modules delegate_commands) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren + -open Tezos_stdlib_unix + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_009_PsFLoren + -open Tezos_client_commands + -open Tezos_baking_009_PsFLoren + -open Tezos_rpc))) + +(library + (name tezos_baking_009_PsFLoren_commands_registration) + (public_name tezos-baking-009-PsFLoren-commands.registration) + (libraries tezos-base + tezos-protocol-009-PsFLoren + tezos-protocol-environment + tezos-shell-services + tezos-client-base + tezos-client-009-PsFLoren + tezos-client-commands + tezos-baking-009-PsFLoren + tezos-baking-009-PsFLoren-commands + tezos-rpc) + (library_flags (:standard -linkall)) + (modules delegate_commands_registration) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_009_PsFLoren + -open Tezos_client_commands + -open Tezos_baking_009_PsFLoren + -open Tezos_baking_009_PsFLoren_commands + -open Tezos_rpc))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/lib_delegate/dune-project b/src/proto_009_PsFLoren/lib_delegate/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..b20f594e4824d8e119274ee5b063559254f2f7c5 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-accuser-alpha-commands) diff --git a/src/proto_009_PsFLoren/lib_delegate/logging.ml b/src/proto_009_PsFLoren/lib_delegate/logging.ml new file mode 100644 index 0000000000000000000000000000000000000000..aaa7172e0375db2e1d89eed3606b50ad3b0afd32 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/logging.ml @@ -0,0 +1,154 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let timestamp_tag = + Tag.def ~doc:"Timestamp when event occurred" "timestamp" Time.System.pp_hum + +let valid_ops = Tag.def ~doc:"Valid Operations" "valid_ops" Format.pp_print_int + +let op_count = + Tag.def ~doc:"Number of operations" "op_count" Format.pp_print_int + +let refused_ops = + Tag.def ~doc:"Refused Operations" "refused_ops" Format.pp_print_int + +let bake_priority_tag = + Tag.def ~doc:"Baking priority" "bake_priority" Format.pp_print_int + +let fitness_tag = Tag.def ~doc:"Fitness" "fitness" Fitness.pp + +let current_slots_tag = + Tag.def + ~doc:"Number of baking slots that can be baked at this time" + "current_slots" + Format.pp_print_int + +let future_slots_tag = + Tag.def + ~doc: + "Number of baking slots in the foreseeable future but not yet bakeable" + "future_slots" + Format.pp_print_int + +let timespan_tag = Tag.def ~doc:"Timespan in seconds" "timespan" Ptime.Span.pp + +let filename_tag = Tag.def ~doc:"Filename" "filename" Format.pp_print_text + +let signed_header_tag = + Tag.def ~doc:"Signed header" "signed_header" (fun fmt x -> + Hex.pp fmt (Hex.of_bytes x)) + +let signed_operation_tag = + Tag.def ~doc:"Signed operation" "signed_operation" (fun fmt x -> + Hex.pp fmt (Hex.of_bytes x)) + +let operations_tag = + Tag.def + ~doc:"Block Operations" + "operations" + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf "+") + (fun ppf operations -> Format.fprintf ppf "%d" (List.length operations))) + +let raw_operations_tag = + Tag.def ~doc:"Raw operations" "raw_operations" (fun fmt raw_ops -> + let pp_op fmt op = + let json = Data_encoding.Json.construct Operation.raw_encoding op in + Format.fprintf fmt "%a" Data_encoding.Json.pp json + in + Format.fprintf + fmt + "@[%a@]" + (Format.pp_print_list ~pp_sep:Format.pp_print_cut pp_op) + raw_ops) + +let bake_op_count_tag = + Tag.def ~doc:"Bake Operation Count" "operation_count" Format.pp_print_int + +let endorsement_slot_tag = + Tag.def ~doc:"Endorsement Slot" "endorsement_slot" Format.pp_print_int + +let endorsement_slots_tag = + Tag.def + ~doc:"Endorsement Slots" + "endorsement_slots" + Format.(fun ppf v -> pp_print_int ppf (List.length v)) + +let denounced_endorsements_slots_tag = + Tag.def + ~doc:"Endorsement Slots" + "denounced_endorsement_slots" + Format.(pp_print_list pp_print_int) + +let denouncement_source_tag = + Tag.def ~doc:"Denounce Source" "source" Format.pp_print_text + +let level_tag = Tag.def ~doc:"Level" "level" Raw_level.pp + +let nonce_tag = + Tag.def + ~doc:"Nonce" + "nonce" + Data_encoding.Json.( + fun ppf nonce -> pp ppf (construct Nonce.encoding nonce)) + +let chain_tag = + Tag.def + ~doc:"Chain selector" + "chain" + Format.( + fun ppf chain -> + pp_print_string ppf @@ Block_services.chain_to_string chain) + +let block_tag = + Tag.def + ~doc:"Block selector" + "block" + Format.( + fun ppf block -> pp_print_string ppf @@ Block_services.to_string block) + +let worker_tag = + Tag.def ~doc:"Worker in which event occurred" "worker" Format.pp_print_text + +let block_header_tag = + Tag.def ~doc:"Raw block header" "block_header" (fun ppf _ -> + Format.fprintf ppf "[raw block header]") + +let conflicting_endorsements_tag = + Tag.def + ~doc:"Two conflicting endorsements signed by the same key" + "conflicting_endorsements" + Format.( + fun ppf (a, b) -> + fprintf + ppf + "%a / %a" + Operation_hash.pp + (Operation.hash a) + Operation_hash.pp + (Operation.hash b)) diff --git a/src/proto_009_PsFLoren/lib_delegate/logging.mli b/src/proto_009_PsFLoren/lib_delegate/logging.mli new file mode 100644 index 0000000000000000000000000000000000000000..544b2ef25007ecdf1ec39a490229604ad94f9de8 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/logging.mli @@ -0,0 +1,80 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +val timestamp_tag : Time.System.t Tag.def + +val valid_ops : int Tag.def + +val op_count : int Tag.def + +val refused_ops : int Tag.def + +val bake_priority_tag : int Tag.def + +val fitness_tag : Fitness.t Tag.def + +val current_slots_tag : int Tag.def + +val future_slots_tag : int Tag.def + +val timespan_tag : Time.System.Span.t Tag.def + +val filename_tag : string Tag.def + +val signed_header_tag : Bytes.t Tag.def + +val signed_operation_tag : Bytes.t Tag.def + +val operations_tag : Tezos_base.Operation.t list list Tag.def + +val raw_operations_tag : Operation.raw list Tag.def + +val bake_op_count_tag : int Tag.def + +val endorsement_slot_tag : int Tag.def + +val endorsement_slots_tag : int list Tag.def + +val denounced_endorsements_slots_tag : int list Tag.def + +val denouncement_source_tag : string Tag.def + +val level_tag : Raw_level.t Tag.def + +val nonce_tag : Nonce.t Tag.def + +val chain_tag : Block_services.chain Tag.def + +val block_tag : Block_services.block Tag.def + +val worker_tag : string Tag.def + +val block_header_tag : Block_header.t Tag.def + +val conflicting_endorsements_tag : + (Kind.endorsement operation * Kind.endorsement operation) Tag.def diff --git a/src/proto_009_PsFLoren/lib_delegate/tezos-accuser-009-PsFLoren-commands.opam b/src/proto_009_PsFLoren/lib_delegate/tezos-accuser-009-PsFLoren-commands.opam new file mode 100644 index 0000000000000000000000000000000000000000..17a1083d692b7c0a0e97aa69728bbb2fbb1afb3e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/tezos-accuser-009-PsFLoren-commands.opam @@ -0,0 +1,24 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-protocol-environment" + "tezos-protocol-009-PsFLoren" + "tezos-shell-services" + "tezos-client-base" + "tezos-client-commands" + "tezos-client-009-PsFLoren" + "tezos-baking-009-PsFLoren" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol-specific commands for `tezos-accuser`" diff --git a/src/proto_009_PsFLoren/lib_delegate/tezos-baking-009-PsFLoren-commands.opam b/src/proto_009_PsFLoren/lib_delegate/tezos-baking-009-PsFLoren-commands.opam new file mode 100644 index 0000000000000000000000000000000000000000..19c2177f78f8a4fb8fd7047e06dd8be18f7f90de --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/tezos-baking-009-PsFLoren-commands.opam @@ -0,0 +1,25 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-protocol-environment" + "tezos-protocol-009-PsFLoren" + "tezos-shell-services" + "tezos-shell-context" + "tezos-client-base" + "tezos-client-commands" + "tezos-client-009-PsFLoren" + "tezos-baking-009-PsFLoren" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol-specific commands for baking" diff --git a/src/proto_009_PsFLoren/lib_delegate/tezos-baking-009-PsFLoren.opam b/src/proto_009_PsFLoren/lib_delegate/tezos-baking-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..29abfde595461b901b1315714a13f182a931c655 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/tezos-baking-009-PsFLoren.opam @@ -0,0 +1,27 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-version" + "tezos-protocol-environment" + "tezos-protocol-009-PsFLoren" + "tezos-shell-context" + "tezos-shell-services" + "tezos-client-base" + "tezos-client-commands" + "tezos-client-009-PsFLoren" + "lwt-canceler" { >= "0.3" & < "0.4" } + "lwt-exit" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: base library for `tezos-baker/endorser/accuser`" diff --git a/src/proto_009_PsFLoren/lib_delegate/tezos-endorser-009-PsFLoren-commands.opam b/src/proto_009_PsFLoren/lib_delegate/tezos-endorser-009-PsFLoren-commands.opam new file mode 100644 index 0000000000000000000000000000000000000000..aa5c9c4c9e42d39d1ce141dec8548ce9a53c69df --- /dev/null +++ b/src/proto_009_PsFLoren/lib_delegate/tezos-endorser-009-PsFLoren-commands.opam @@ -0,0 +1,24 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-protocol-environment" + "tezos-protocol-009-PsFLoren" + "tezos-shell-services" + "tezos-client-base" + "tezos-client-commands" + "tezos-client-009-PsFLoren" + "tezos-baking-009-PsFLoren" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol-specific commands for `tezos-endorser`" diff --git a/src/proto_009_PsFLoren/lib_parameters/.ocamlformat b/src/proto_009_PsFLoren/lib_parameters/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_parameters/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_parameters/default_parameters.ml b/src/proto_009_PsFLoren/lib_parameters/default_parameters.ml new file mode 100644 index 0000000000000000000000000000000000000000..88537b786d65e98006919017a9ac7e2d843d868c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_parameters/default_parameters.ml @@ -0,0 +1,154 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +let constants_mainnet = + Constants. + { + preserved_cycles = 5; + blocks_per_cycle = 4096l; + blocks_per_commitment = 32l; + blocks_per_roll_snapshot = 256l; + blocks_per_voting_period = 20480l; + time_between_blocks = List.map Period.of_seconds_exn [60L; 40L]; + endorsers_per_block = 32; + hard_gas_limit_per_operation = Gas.Arith.(integral_of_int_exn 1_040_000); + hard_gas_limit_per_block = Gas.Arith.(integral_of_int_exn 10_400_000); + proof_of_work_threshold = Int64.(sub (shift_left 1L 46) 1L); + tokens_per_roll = Tez.(mul_exn one 8_000); + michelson_maximum_type_size = 1000; + seed_nonce_revelation_tip = + (match Tez.(one /? 8L) with Ok c -> c | Error _ -> assert false); + origination_size = 257; + block_security_deposit = Tez.(mul_exn one 512); + endorsement_security_deposit = Tez.(mul_exn one 64); + baking_reward_per_endorsement = + Tez.[of_mutez_exn 1_250_000L; of_mutez_exn 187_500L]; + endorsement_reward = Tez.[of_mutez_exn 1_250_000L; of_mutez_exn 833_333L]; + hard_storage_limit_per_operation = Z.of_int 60_000; + cost_per_byte = Tez.of_mutez_exn 250L; + quorum_min = 20_00l; + (* quorum is in centile of a percentage *) + quorum_max = 70_00l; + min_proposal_quorum = 5_00l; + initial_endorsers = 24; + delay_per_missing_endorsement = Period.of_seconds_exn 8L; + } + +let constants_sandbox = + Constants. + { + constants_mainnet with + preserved_cycles = 2; + blocks_per_cycle = 8l; + blocks_per_commitment = 4l; + blocks_per_roll_snapshot = 4l; + blocks_per_voting_period = 64l; + time_between_blocks = List.map Period.of_seconds_exn [1L; 0L]; + proof_of_work_threshold = Int64.of_int (-1); + initial_endorsers = 1; + delay_per_missing_endorsement = Period.of_seconds_exn 1L; + } + +let constants_test = + Constants. + { + constants_mainnet with + blocks_per_cycle = 128l; + blocks_per_commitment = 4l; + blocks_per_roll_snapshot = 32l; + blocks_per_voting_period = 256l; + time_between_blocks = List.map Period.of_seconds_exn [1L; 0L]; + proof_of_work_threshold = Int64.of_int (-1); + initial_endorsers = 1; + delay_per_missing_endorsement = Period.of_seconds_exn 1L; + } + +let bootstrap_accounts_strings = + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"; + "edpktzNbDAUjUk697W7gYg2CRuBQjyPxbEg8dLccYYwKSKvkPvjtV9"; + "edpkuTXkJDGcFd5nh6VvMz8phXxU3Bi7h6hqgywNFi1vZTfQNnS1RV"; + "edpkuFrRoDSEbJYgxRtLx2ps82UdaYc1WwfS9sE11yhauZt5DgCHbU"; + "edpkv8EUUH68jmo3f7Um5PezmfGrRF24gnfLpH3sVNwJnV5bVCxL2n" ] + +let bootstrap_balance = Tez.of_mutez_exn 4_000_000_000_000L + +let bootstrap_accounts = + List.map + (fun s -> + let public_key = Signature.Public_key.of_b58check_exn s in + let public_key_hash = Signature.Public_key.hash public_key in + Parameters. + { + public_key_hash; + public_key = Some public_key; + amount = bootstrap_balance; + }) + bootstrap_accounts_strings + +(* TODO this could be generated from OCaml together with the faucet + for now these are hardcoded values in the tests *) +let commitments = + let json_result = + Data_encoding.Json.from_string + {json| + [ + [ "btz1bRL4X5BWo2Fj4EsBdUwexXqgTf75uf1qa", "23932454669343" ], + [ "btz1SxjV1syBgftgKy721czKi3arVkVwYUFSv", "72954577464032" ], + [ "btz1LtoNCjiW23txBTenALaf5H6NKF1L3c1gw", "217487035428348" ], + [ "btz1SUd3mMhEBcWudrn8u361MVAec4WYCcFoy", "4092742372031" ], + [ "btz1MvBXf4orko1tsGmzkjLbpYSgnwUjEe81r", "17590039016550" ], + [ "btz1LoDZ3zsjgG3k3cqTpUMc9bsXbchu9qMXT", "26322312350555" ], + [ "btz1RMfq456hFV5AeDiZcQuZhoMv2dMpb9hpP", "244951387881443" ], + [ "btz1Y9roTh4A7PsMBkp8AgdVFrqUDNaBE59y1", "80065050465525" ], + [ "btz1Q1N2ePwhVw5ED3aaRVek6EBzYs1GDkSVD", "3569618927693" ], + [ "btz1VFFVsVMYHd5WfaDTAt92BeQYGK8Ri4eLy", "9034781424478" ] + ]|json} + in + match json_result with + | Error err -> + raise (Failure err) + | Ok json -> + Data_encoding.Json.destruct (Data_encoding.list Commitment.encoding) json + +let make_bootstrap_account (pkh, pk, amount) = + Parameters.{public_key_hash = pkh; public_key = Some pk; amount} + +let parameters_of_constants ?(bootstrap_accounts = bootstrap_accounts) + ?(bootstrap_contracts = []) ?(with_commitments = false) constants = + let commitments = if with_commitments then commitments else [] in + Parameters. + { + bootstrap_accounts; + bootstrap_contracts; + commitments; + constants; + security_deposit_ramp_up_cycles = None; + no_reward_cycles = None; + } + +let json_of_parameters parameters = + Data_encoding.Json.construct Parameters.encoding parameters diff --git a/src/proto_009_PsFLoren/lib_parameters/default_parameters.mli b/src/proto_009_PsFLoren/lib_parameters/default_parameters.mli new file mode 100644 index 0000000000000000000000000000000000000000..0a99181fe345d1ef89042681128e84e234fcfeb8 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_parameters/default_parameters.mli @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +val constants_mainnet : Constants.parametric + +val constants_sandbox : Constants.parametric + +val constants_test : Constants.parametric + +val make_bootstrap_account : + Signature.public_key_hash * Signature.public_key * Tez.t -> + Parameters.bootstrap_account + +val parameters_of_constants : + ?bootstrap_accounts:Parameters.bootstrap_account list -> + ?bootstrap_contracts:Parameters.bootstrap_contract list -> + ?with_commitments:bool -> + Constants.parametric -> + Parameters.t + +val json_of_parameters : Parameters.t -> Data_encoding.json diff --git a/src/proto_009_PsFLoren/lib_parameters/dune b/src/proto_009_PsFLoren/lib_parameters/dune new file mode 100644 index 0000000000000000000000000000000000000000..a147ce4b0ec28c6d250637632c0d2385db3b89fc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_parameters/dune @@ -0,0 +1,44 @@ +(library + (name tezos_protocol_009_PsFLoren_parameters) + (public_name tezos-protocol-009-PsFLoren-parameters) + (modules :standard \ gen) + (libraries tezos-base + tezos-protocol-environment + tezos-protocol-009-PsFLoren) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren + -linkall)) +) + +(executable + (name gen) + (libraries tezos-base + tezos-protocol-009-PsFLoren-parameters) + (modules gen) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_009_PsFLoren_parameters + -linkall))) + +(rule + (targets sandbox-parameters.json) + (deps gen.exe) + (action (run %{deps} --sandbox))) + +(rule + (targets test-parameters.json) + (deps gen.exe) + (action (run %{deps} --test))) + +(rule + (targets mainnet-parameters.json) + (deps gen.exe) + (action (run %{deps} --mainnet))) + +(install + (section lib) + (files sandbox-parameters.json test-parameters.json mainnet-parameters.json)) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/lib_parameters/dune-project b/src/proto_009_PsFLoren/lib_parameters/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..8b12287e8e38ba126db4892171ec50ed5f3151f0 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_parameters/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-protocol-alpha-parameters) diff --git a/src/proto_009_PsFLoren/lib_parameters/gen.ml b/src/proto_009_PsFLoren/lib_parameters/gen.ml new file mode 100644 index 0000000000000000000000000000000000000000..93a0a459dd39e465da0a5689ad7e0ca609df5788 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_parameters/gen.ml @@ -0,0 +1,61 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Prints the json encoding of the parametric constants of protocol alpha. + $ dune utop src/proto_alpha/lib_protocol/test/helpers/ constants.ml +*) + +let () = + let print_usage_and_fail s = + Printf.eprintf "Usage: %s [ --sandbox | --test | --mainnet ]" Sys.argv.(0) ; + raise (Invalid_argument s) + in + let dump parameters file = + let str = + Data_encoding.Json.to_string + (Default_parameters.json_of_parameters parameters) + in + let fd = open_out file in + output_string fd str ; close_out fd + in + if Array.length Sys.argv < 2 then print_usage_and_fail "" + else + match Sys.argv.(1) with + | "--sandbox" -> + dump + Default_parameters.(parameters_of_constants constants_sandbox) + "sandbox-parameters.json" + | "--test" -> + dump + Default_parameters.( + parameters_of_constants ~with_commitments:true constants_sandbox) + "test-parameters.json" + | "--mainnet" -> + dump + Default_parameters.( + parameters_of_constants ~with_commitments:true constants_mainnet) + "mainnet-parameters.json" + | s -> + print_usage_and_fail s diff --git a/src/proto_009_PsFLoren/lib_parameters/tezos-protocol-009-PsFLoren-parameters.opam b/src/proto_009_PsFLoren/lib_parameters/tezos-protocol-009-PsFLoren-parameters.opam new file mode 100644 index 0000000000000000000000000000000000000000..b42aed05deb1804c0d316d24c0df9710d5f0549a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_parameters/tezos-protocol-009-PsFLoren-parameters.opam @@ -0,0 +1,19 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-protocol-environment" + "tezos-protocol-009-PsFLoren" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: parameters" diff --git a/src/proto_009_PsFLoren/lib_plugin/.ocamlformat b/src/proto_009_PsFLoren/lib_plugin/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_plugin/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_plugin/dune b/src/proto_009_PsFLoren/lib_plugin/dune new file mode 100644 index 0000000000000000000000000000000000000000..7668943a4f3da1ee34c4bbe1a26003be8acac81c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_plugin/dune @@ -0,0 +1,26 @@ +(library + (name tezos_protocol_plugin_009_PsFLoren) + (public_name tezos-protocol-plugin-009-PsFLoren) + (libraries tezos-base + tezos-embedded-protocol-009-PsFLoren + tezos-protocol-009-PsFLoren) + (modules (:standard) \ Registerer) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_embedded_protocol_009_PsFLoren + -open Tezos_protocol_009_PsFLoren))) + +(library + (name tezos_protocol_plugin_009_PsFLoren_registerer) + (public_name tezos-protocol-plugin-009-PsFLoren-registerer) + (libraries tezos-base + tezos-protocol-plugin-009-PsFLoren + tezos-shell) + (modules Registerer) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_protocol_plugin_009_PsFLoren + -open Tezos_shell))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/lib_plugin/dune-project b/src/proto_009_PsFLoren/lib_plugin/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..ffd15c823a37ebe6b7873e39b4022dc8229f66b9 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_plugin/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-filters-alpha) diff --git a/src/proto_009_PsFLoren/lib_plugin/plugin.ml b/src/proto_009_PsFLoren/lib_plugin/plugin.ml new file mode 100644 index 0000000000000000000000000000000000000000..ec0825c16bf770cef125f528223d9e958ed2d960 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_plugin/plugin.ml @@ -0,0 +1,444 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Nomadic Development. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +module Proto = Registerer.Registered + +module Mempool = struct + type nanotez = Q.t + + let nanotez_enc : nanotez Data_encoding.t = + let open Data_encoding in + def + "nanotez" + ~title:"A thousandth of a mutez" + ~description:"One thousand nanotez make a mutez (1 tez = 1e9 nanotez)" + (conv + (fun q -> (q.Q.num, q.Q.den)) + (fun (num, den) -> {Q.num; den}) + (tup2 z z)) + + type config = { + minimal_fees : Tez.t; + minimal_nanotez_per_gas_unit : nanotez; + minimal_nanotez_per_byte : nanotez; + allow_script_failure : bool; + } + + let default_minimal_fees = + match Tez.of_mutez 100L with None -> assert false | Some t -> t + + let default_minimal_nanotez_per_gas_unit = Q.of_int 100 + + let default_minimal_nanotez_per_byte = Q.of_int 1000 + + let config_encoding : config Data_encoding.t = + let open Data_encoding in + conv + (fun { minimal_fees; + minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte; + allow_script_failure } -> + ( minimal_fees, + minimal_nanotez_per_gas_unit, + minimal_nanotez_per_byte, + allow_script_failure )) + (fun ( minimal_fees, + minimal_nanotez_per_gas_unit, + minimal_nanotez_per_byte, + allow_script_failure ) -> + { + minimal_fees; + minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte; + allow_script_failure; + }) + (obj4 + (dft "minimal_fees" Tez.encoding default_minimal_fees) + (dft + "minimal_nanotez_per_gas_unit" + nanotez_enc + default_minimal_nanotez_per_gas_unit) + (dft + "minimal_nanotez_per_byte" + nanotez_enc + default_minimal_nanotez_per_byte) + (dft "allow_script_failure" bool true)) + + let default_config = + { + minimal_fees = default_minimal_fees; + minimal_nanotez_per_gas_unit = default_minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte = default_minimal_nanotez_per_byte; + allow_script_failure = true; + } + + let get_manager_operation_gas_and_fee contents = + let open Operation in + let l = to_list (Contents_list contents) in + List.fold_left + (fun acc -> function + | Contents (Manager_operation {fee; gas_limit; _}) -> ( + match acc with + | Error _ as e -> + e + | Ok (total_fee, total_gas) -> ( + match Tez.(total_fee +? fee) with + | Ok total_fee -> + Ok (total_fee, Gas.Arith.add total_gas gas_limit) + | Error _ as e -> + e ) ) | _ -> acc) + (Ok (Tez.zero, Gas.Arith.zero)) + l + + let pre_filter_manager : + type t. config -> t Kind.manager contents_list -> int -> bool = + fun config op size -> + match get_manager_operation_gas_and_fee op with + | Error _ -> + false + | Ok (fee, gas) -> + let fees_in_nanotez = + Q.mul (Q.of_int64 (Tez.to_mutez fee)) (Q.of_int 1000) + in + let minimal_fees_in_nanotez = + Q.mul (Q.of_int64 (Tez.to_mutez config.minimal_fees)) (Q.of_int 1000) + in + let minimal_fees_for_gas_in_nanotez = + Q.mul + config.minimal_nanotez_per_gas_unit + (Q.of_bigint @@ Gas.Arith.integral_to_z gas) + in + let minimal_fees_for_size_in_nanotez = + Q.mul config.minimal_nanotez_per_byte (Q.of_int size) + in + Q.compare + fees_in_nanotez + (Q.add + minimal_fees_in_nanotez + (Q.add + minimal_fees_for_gas_in_nanotez + minimal_fees_for_size_in_nanotez)) + >= 0 + + let pre_filter config + (Operation_data {contents; _} as op : Operation.packed_protocol_data) = + let bytes = + ( WithExceptions.Option.get ~loc:__LOC__ + @@ Data_encoding.Binary.fixed_length + Tezos_base.Operation.shell_header_encoding ) + + Data_encoding.Binary.length Operation.protocol_data_encoding op + in + match contents with + | Single (Endorsement _) -> + false (* legacy format *) + | Single (Failing_noop _) -> + false + | Single (Endorsement_with_slot _) -> + true + | Single (Seed_nonce_revelation _) -> + true + | Single (Double_endorsement_evidence _) -> + true + | Single (Double_baking_evidence _) -> + true + | Single (Activate_account _) -> + true + | Single (Proposals _) -> + true + | Single (Ballot _) -> + true + | Single (Manager_operation _) as op -> + pre_filter_manager config op bytes + | Cons (Manager_operation _, _) as op -> + pre_filter_manager config op bytes + + open Apply_results + + let rec post_filter_manager : + type t. + Alpha_context.t -> + t Kind.manager contents_result_list -> + config -> + bool Lwt.t = + fun ctxt op config -> + match op with + | Single_result (Manager_operation_result {operation_result; _}) -> ( + match operation_result with + | Applied _ -> + Lwt.return_true + | Skipped _ | Failed _ | Backtracked _ -> + Lwt.return config.allow_script_failure ) + | Cons_result (Manager_operation_result res, rest) -> ( + post_filter_manager + ctxt + (Single_result (Manager_operation_result res)) + config + >>= function + | false -> + Lwt.return_false + | true -> + post_filter_manager ctxt rest config ) + + let post_filter config ~validation_state_before:_ + ~validation_state_after:({ctxt; _} : validation_state) (_op, receipt) = + match receipt with + | No_operation_metadata -> + assert false (* only for multipass validator *) + | Operation_metadata {contents} -> ( + match contents with + | Single_result (Endorsement_result _) -> + Lwt.return_false (* legacy format *) + | Single_result (Endorsement_with_slot_result _) -> + Lwt.return_true + | Single_result (Seed_nonce_revelation_result _) -> + Lwt.return_true + | Single_result (Double_endorsement_evidence_result _) -> + Lwt.return_true + | Single_result (Double_baking_evidence_result _) -> + Lwt.return_true + | Single_result (Activate_account_result _) -> + Lwt.return_true + | Single_result Proposals_result -> + Lwt.return_true + | Single_result Ballot_result -> + Lwt.return_true + | Single_result (Manager_operation_result _) as op -> + post_filter_manager ctxt op config + | Cons_result (Manager_operation_result _, _) as op -> + post_filter_manager ctxt op config ) +end + +module RPC = struct + open Environment + + module Unparse_types = struct + (* Same as the unparsing functions for types in Script_ir_translator but + does not consume gas and never folds (pair a (pair b c)) *) + + open Script_ir_translator + open Micheline + open Michelson_v1_primitives + open Script_ir_annot + open Script_typed_ir + + let rec unparse_comparable_ty : type a. a comparable_ty -> Script.node = + function + | Unit_key tname -> + Prim (-1, T_unit, [], unparse_type_annot tname) + | Never_key tname -> + Prim (-1, T_never, [], unparse_type_annot tname) + | Int_key tname -> + Prim (-1, T_int, [], unparse_type_annot tname) + | Nat_key tname -> + Prim (-1, T_nat, [], unparse_type_annot tname) + | Signature_key tname -> + Prim (-1, T_signature, [], unparse_type_annot tname) + | String_key tname -> + Prim (-1, T_string, [], unparse_type_annot tname) + | Bytes_key tname -> + Prim (-1, T_bytes, [], unparse_type_annot tname) + | Mutez_key tname -> + Prim (-1, T_mutez, [], unparse_type_annot tname) + | Bool_key tname -> + Prim (-1, T_bool, [], unparse_type_annot tname) + | Key_hash_key tname -> + Prim (-1, T_key_hash, [], unparse_type_annot tname) + | Key_key tname -> + Prim (-1, T_key, [], unparse_type_annot tname) + | Timestamp_key tname -> + Prim (-1, T_timestamp, [], unparse_type_annot tname) + | Address_key tname -> + Prim (-1, T_address, [], unparse_type_annot tname) + | Chain_id_key tname -> + Prim (-1, T_chain_id, [], unparse_type_annot tname) + | Pair_key ((l, al), (r, ar), pname) -> + let tl = add_field_annot al None (unparse_comparable_ty l) in + let tr = add_field_annot ar None (unparse_comparable_ty r) in + Prim (-1, T_pair, [tl; tr], unparse_type_annot pname) + | Union_key ((l, al), (r, ar), tname) -> + let tl = add_field_annot al None (unparse_comparable_ty l) in + let tr = add_field_annot ar None (unparse_comparable_ty r) in + Prim (-1, T_or, [tl; tr], unparse_type_annot tname) + | Option_key (t, tname) -> + Prim + (-1, T_option, [unparse_comparable_ty t], unparse_type_annot tname) + + (* Uncomment when rebasing on top of Baking account *) + (* | Baker_hash_key tname -> + * Prim (-1, T_baker_hash, [], unparse_type_annot tname) + * | Pvss_key_key tname -> + * Prim (-1, T_pvss_key, [], unparse_type_annot tname) *) + + let unparse_memo_size memo_size = + let z = Alpha_context.Sapling.Memo_size.unparse_to_z memo_size in + Int (-1, z) + + let rec unparse_ty : type a. a ty -> Script.node = + fun ty -> + let return (name, args, annot) = Prim (-1, name, args, annot) in + match ty with + | Unit_t tname -> + return (T_unit, [], unparse_type_annot tname) + | Int_t tname -> + return (T_int, [], unparse_type_annot tname) + | Nat_t tname -> + return (T_nat, [], unparse_type_annot tname) + | Signature_t tname -> + return (T_signature, [], unparse_type_annot tname) + | String_t tname -> + return (T_string, [], unparse_type_annot tname) + | Bytes_t tname -> + return (T_bytes, [], unparse_type_annot tname) + | Mutez_t tname -> + return (T_mutez, [], unparse_type_annot tname) + | Bool_t tname -> + return (T_bool, [], unparse_type_annot tname) + | Key_hash_t tname -> + return (T_key_hash, [], unparse_type_annot tname) + | Key_t tname -> + return (T_key, [], unparse_type_annot tname) + | Timestamp_t tname -> + return (T_timestamp, [], unparse_type_annot tname) + | Address_t tname -> + return (T_address, [], unparse_type_annot tname) + | Operation_t tname -> + return (T_operation, [], unparse_type_annot tname) + | Chain_id_t tname -> + return (T_chain_id, [], unparse_type_annot tname) + | Never_t tname -> + return (T_never, [], unparse_type_annot tname) + | Bls12_381_g1_t tname -> + return (T_bls12_381_g1, [], unparse_type_annot tname) + | Bls12_381_g2_t tname -> + return (T_bls12_381_g2, [], unparse_type_annot tname) + | Bls12_381_fr_t tname -> + return (T_bls12_381_fr, [], unparse_type_annot tname) + | Contract_t (ut, tname) -> + let t = unparse_ty ut in + return (T_contract, [t], unparse_type_annot tname) + | Pair_t ((utl, l_field, l_var), (utr, r_field, r_var), tname) -> + let annot = unparse_type_annot tname in + let utl = unparse_ty utl in + let tl = add_field_annot l_field l_var utl in + let utr = unparse_ty utr in + let tr = add_field_annot r_field r_var utr in + return (T_pair, [tl; tr], annot) + | Union_t ((utl, l_field), (utr, r_field), tname) -> + let annot = unparse_type_annot tname in + let utl = unparse_ty utl in + let tl = add_field_annot l_field None utl in + let utr = unparse_ty utr in + let tr = add_field_annot r_field None utr in + return (T_or, [tl; tr], annot) + | Lambda_t (uta, utr, tname) -> + let ta = unparse_ty uta in + let tr = unparse_ty utr in + return (T_lambda, [ta; tr], unparse_type_annot tname) + | Option_t (ut, tname) -> + let annot = unparse_type_annot tname in + let ut = unparse_ty ut in + return (T_option, [ut], annot) + | List_t (ut, tname) -> + let t = unparse_ty ut in + return (T_list, [t], unparse_type_annot tname) + | Ticket_t (ut, tname) -> + let t = unparse_comparable_ty ut in + return (T_ticket, [t], unparse_type_annot tname) + | Set_t (ut, tname) -> + let t = unparse_comparable_ty ut in + return (T_set, [t], unparse_type_annot tname) + | Map_t (uta, utr, tname) -> + let ta = unparse_comparable_ty uta in + let tr = unparse_ty utr in + return (T_map, [ta; tr], unparse_type_annot tname) + | Big_map_t (uta, utr, tname) -> + let ta = unparse_comparable_ty uta in + let tr = unparse_ty utr in + return (T_big_map, [ta; tr], unparse_type_annot tname) + | Sapling_transaction_t (memo_size, tname) -> + return + ( T_sapling_transaction, + [unparse_memo_size memo_size], + unparse_type_annot tname ) + | Sapling_state_t (memo_size, tname) -> + return + ( T_sapling_state, + [unparse_memo_size memo_size], + unparse_type_annot tname ) + + (* Uncomment when rebasing on top of Baking account *) + (* | Baker_hash_t tname -> + * return (T_baker_hash, [], unparse_type_annot tname) + * | Pvss_key_t tname -> + * return (T_pvss_key, [], unparse_type_annot tname) + * | Baker_operation_t tname -> + * return (T_baker_operation, [], unparse_type_annot tname) *) + end + + let helpers_path = RPC_path.(open_root / "helpers" / "scripts") + + let normalize_type = + let open Data_encoding in + RPC_service.post_service + ~description: + "Normalizes some Michelson type by expanding `pair a b c` as `pair a \ + (pair b c)" + ~input:(obj1 (req "type" Script.expr_encoding)) + ~output:(obj1 (req "normalized" Script.expr_encoding)) + ~query:RPC_query.empty + RPC_path.(helpers_path / "normalize_type") + + let rpc_services = + let patched_services = + ref (RPC_directory.empty : Updater.rpc_context RPC_directory.t) + in + let register0_fullctxt s f = + patched_services := + RPC_directory.register !patched_services s (fun ctxt q i -> + Services_registration.rpc_init ctxt >>=? fun ctxt -> f ctxt q i) + in + let register0 s f = register0_fullctxt s (fun {context; _} -> f context) in + register0 normalize_type (fun ctxt () typ -> + let open Script_ir_translator in + let ctxt = Gas.set_unlimited ctxt in + (* Unfortunately, Script_ir_translator.parse_any_ty is not exported *) + Script_ir_translator.parse_ty + ctxt + ~legacy:true + ~allow_lazy_storage:true + ~allow_operation:true + ~allow_contract:true + ~allow_ticket:true + (Micheline.root typ) + >>?= fun (Ex_ty typ, _ctxt) -> + let normalized = Unparse_types.unparse_ty typ in + return @@ Micheline.strip_locations normalized) ; + RPC_directory.merge rpc_services !patched_services + + let normalize_type ctxt block ~ty = + RPC_context.make_call0 normalize_type ctxt block () ty +end diff --git a/src/proto_009_PsFLoren/lib_plugin/registerer.ml b/src/proto_009_PsFLoren/lib_plugin/registerer.ml new file mode 100644 index 0000000000000000000000000000000000000000..8824909c91c6f72ba31d00852ac9d0455ac79882 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_plugin/registerer.ml @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Development. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = Prevalidator_filters.register (module Plugin) diff --git a/src/proto_009_PsFLoren/lib_plugin/tezos-protocol-plugin-009-PsFLoren-registerer.opam b/src/proto_009_PsFLoren/lib_plugin/tezos-protocol-plugin-009-PsFLoren-registerer.opam new file mode 100644 index 0000000000000000000000000000000000000000..2eca3b8a751f1136fa52d61bd21d1d9f5c0d8f4d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_plugin/tezos-protocol-plugin-009-PsFLoren-registerer.opam @@ -0,0 +1,19 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-protocol-plugin-009-PsFLoren" + "tezos-shell" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol plugin registerer" diff --git a/src/proto_009_PsFLoren/lib_plugin/tezos-protocol-plugin-009-PsFLoren.opam b/src/proto_009_PsFLoren/lib_plugin/tezos-protocol-plugin-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..c0087165826a1504ebd8948e17cb34fb51078cb4 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_plugin/tezos-protocol-plugin-009-PsFLoren.opam @@ -0,0 +1,18 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "tezos-tooling" { with-test } + "dune" { >= "2.0" } + "tezos-base" + "tezos-embedded-protocol-009-PsFLoren" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol plugin" diff --git a/src/proto_009_PsFLoren/lib_protocol/.ocamlformat b/src/proto_009_PsFLoren/lib_protocol/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_protocol/TEZOS_PROTOCOL b/src/proto_009_PsFLoren/lib_protocol/TEZOS_PROTOCOL new file mode 100644 index 0000000000000000000000000000000000000000..ee5039b55848ed438f120791f835d2378bb7acad --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/TEZOS_PROTOCOL @@ -0,0 +1,93 @@ +{ + "expected_env_version": 2, + "hash": "PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i", + "modules": [ + "Misc", + "Storage_description", + "State_hash", + "Nonce_hash", + "Script_expr_hash", + "Contract_hash", + "Blinded_public_key_hash", + + "Tez_repr", + "Period_repr", + "Time_repr", + "Fixed_point_repr", + "Saturation_repr", + "Gas_limit_repr", + "Constants_repr", + "Fitness_repr", + "Raw_level_repr", + "Cycle_repr", + "Level_repr", + "Seed_repr", + "Voting_period_repr", + "Script_int_repr", + "Script_timestamp_repr", + "Michelson_v1_primitives", + "Script_repr", + "Contract_repr", + "Roll_repr", + "Vote_repr", + "Block_header_repr", + "Operation_repr", + "Manager_repr", + "Commitment_repr", + "Parameters_repr", + "Sapling_repr", + "Lazy_storage_kind", + "Receipt_repr", + + "Raw_context_intf", + "Raw_context", + "Storage_costs", + "Storage_sigs", + "Storage_functors", + "Storage", + + "Constants_storage", + "Level_storage", + "Nonce_storage", + "Seed_storage", + "Roll_storage", + "Delegate_storage", + "Sapling_storage", + "Lazy_storage_diff", + "Contract_storage", + "Bootstrap_storage", + "Fitness_storage", + "Voting_period_storage", + "Vote_storage", + "Commitment_storage", + "Init_storage", + "Fees_storage", + "Sapling_validator", + + "Alpha_context", + + "Script_typed_ir", + "Script_tc_errors", + "Michelson_v1_gas", + "Script_ir_annot", + "Script_ir_translator", + "Script_tc_errors_registration", + "Script_interpreter", + + "Baking", + "Amendment", + "Apply_results", + "Apply", + + "Services_registration", + "Constants_services", + "Sapling_services", + "Contract_services", + "Delegate_services", + "Helpers_services", + "Voting_services", + "Alpha_services", + + "Main" + ] +} diff --git a/src/proto_009_PsFLoren/lib_protocol/alpha_context.ml b/src/proto_009_PsFLoren/lib_protocol/alpha_context.ml new file mode 100644 index 0000000000000000000000000000000000000000..a0e2c784b8dfba5f78e104ce4c682de259e8640d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/alpha_context.ml @@ -0,0 +1,299 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Raw_context.t + +type context = t + +module type BASIC_DATA = sig + type t + + include Compare.S with type t := t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit +end + +module Tez = Tez_repr +module Period = Period_repr + +module Timestamp = struct + include Time_repr + + let current = Raw_context.current_timestamp +end + +include Operation_repr + +module Operation = struct + type 'kind t = 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; + } + + type packed = packed_operation + + let unsigned_encoding = unsigned_operation_encoding + + include Operation_repr +end + +module Block_header = Block_header_repr + +module Vote = struct + include Vote_repr + include Vote_storage +end + +module Raw_level = Raw_level_repr +module Cycle = Cycle_repr +module Script_int = Script_int_repr + +module Script_timestamp = struct + include Script_timestamp_repr + + let now ctxt = + let {Constants_repr.time_between_blocks; _} = Raw_context.constants ctxt in + match time_between_blocks with + | [] -> + failwith + "Internal error: 'time_between_block' constants is an empty list." + | first_delay :: _ -> + let current_timestamp = Raw_context.predecessor_timestamp ctxt in + Time.add current_timestamp (Period_repr.to_seconds first_delay) + |> Timestamp.to_seconds |> of_int64 +end + +module Script = struct + include Michelson_v1_primitives + include Script_repr + + let force_decode_in_context ctxt lexpr = + Script_repr.force_decode lexpr + >>? fun (v, cost) -> + Raw_context.consume_gas ctxt cost >|? fun ctxt -> (v, ctxt) + + let force_bytes_in_context ctxt lexpr = + Script_repr.force_bytes lexpr + >>? fun (b, cost) -> + Raw_context.consume_gas ctxt cost >|? fun ctxt -> (b, ctxt) +end + +module Fees = Fees_storage + +type public_key = Signature.Public_key.t + +type public_key_hash = Signature.Public_key_hash.t + +type signature = Signature.t + +module Constants = struct + include Constants_repr + include Constants_storage +end + +module Voting_period = struct + include Voting_period_repr + include Voting_period_storage +end + +module Gas = struct + include Gas_limit_repr + + type error += Gas_limit_too_high = Raw_context.Gas_limit_too_high + + type error += Block_quota_exceeded = Raw_context.Block_quota_exceeded + + type error += + | Operation_quota_exceeded = Raw_context.Operation_quota_exceeded + + let check_limit = Raw_context.check_gas_limit + + let set_limit = Raw_context.set_gas_limit + + let set_unlimited = Raw_context.set_gas_unlimited + + let consume = Raw_context.consume_gas + + let check_enough = Raw_context.check_enough_gas + + let level = Raw_context.gas_level + + let consumed = Raw_context.gas_consumed + + let block_level = Raw_context.block_gas_level + + (* Necessary to inject costs for Storage_costs into Gas.cost *) + let cost_of_repr cost = cost +end + +module Level = struct + include Level_repr + include Level_storage +end + +module Lazy_storage = struct + module Kind = Lazy_storage_kind + module IdSet = Kind.IdSet + include Lazy_storage_diff + + let legacy_big_map_diff_encoding = + Data_encoding.conv + Contract_storage.Legacy_big_map_diff.of_lazy_storage_diff + Contract_storage.Legacy_big_map_diff.to_lazy_storage_diff + Contract_storage.Legacy_big_map_diff.encoding +end + +module Contract = struct + include Contract_repr + include Contract_storage + + let originate c contract ~balance ~script ~delegate = + raw_originate c contract ~balance ~script ~delegate + + let init_origination_nonce = Raw_context.init_origination_nonce + + let unset_origination_nonce = Raw_context.unset_origination_nonce +end + +module Big_map = struct + include Lazy_storage_kind.Big_map + + let fresh ~temporary c = Lazy_storage.fresh Big_map ~temporary c + + let mem c m k = Storage.Big_map.Contents.mem (c, m) k + + let get_opt c m k = Storage.Big_map.Contents.find (c, m) k + + let exists c id = + Raw_context.consume_gas c (Gas_limit_repr.read_bytes_cost 0) + >>?= fun c -> + Storage.Big_map.Key_type.find c id + >>=? fun kt -> + match kt with + | None -> + return (c, None) + | Some kt -> + Storage.Big_map.Value_type.get c id >|=? fun kv -> (c, Some (kt, kv)) +end + +module Sapling = struct + include Lazy_storage_kind.Sapling_state + include Sapling_repr + include Sapling_storage + include Sapling_validator + + let fresh ~temporary c = Lazy_storage.fresh Sapling_state ~temporary c +end + +module Receipt = Receipt_repr +module Delegate = Delegate_storage + +module Roll = struct + include Roll_repr + include Roll_storage +end + +module Nonce = Nonce_storage + +module Seed = struct + include Seed_repr + include Seed_storage +end + +module Fitness = struct + include Fitness_repr + include Fitness + + type fitness = t + + include Fitness_storage +end + +module Bootstrap = Bootstrap_storage + +module Commitment = struct + include Commitment_repr + include Commitment_storage +end + +module Global = struct + let get_block_priority = Storage.Block_priority.get + + let set_block_priority = Storage.Block_priority.update +end + +let prepare_first_block = Init_storage.prepare_first_block + +let prepare = Init_storage.prepare + +let finalize ?commit_message:message c = + let fitness = Fitness.from_int64 (Fitness.current c) in + let context = Raw_context.recover c in + { + Updater.context; + fitness; + message; + max_operations_ttl = 60; + last_allowed_fork_level = + Raw_level.to_int32 @@ Level.last_allowed_fork_level c; + } + +let activate = Raw_context.activate + +let record_endorsement = Raw_context.record_endorsement + +let allowed_endorsements = Raw_context.allowed_endorsements + +let init_endorsements = Raw_context.init_endorsements + +let included_endorsements = Raw_context.included_endorsements + +let reset_internal_nonce = Raw_context.reset_internal_nonce + +let fresh_internal_nonce = Raw_context.fresh_internal_nonce + +let record_internal_nonce = Raw_context.record_internal_nonce + +let internal_nonce_already_recorded = + Raw_context.internal_nonce_already_recorded + +let add_deposit = Raw_context.add_deposit + +let add_fees = Raw_context.add_fees + +let add_rewards = Raw_context.add_rewards + +let get_deposits = Raw_context.get_deposits + +let get_fees = Raw_context.get_fees + +let get_rewards = Raw_context.get_rewards + +let description = Raw_context.description + +module Parameters = Parameters_repr diff --git a/src/proto_009_PsFLoren/lib_protocol/alpha_context.mli b/src/proto_009_PsFLoren/lib_protocol/alpha_context.mli new file mode 100644 index 0000000000000000000000000000000000000000..ac3cb8fcee904de5e3be8e37c92641623b1d89b6 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/alpha_context.mli @@ -0,0 +1,1640 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type BASIC_DATA = sig + type t + + include Compare.S with type t := t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit +end + +type t + +type context = t + +type public_key = Signature.Public_key.t + +type public_key_hash = Signature.Public_key_hash.t + +type signature = Signature.t + +module Tez : sig + include BASIC_DATA + + type tez = t + + val zero : tez + + val one_mutez : tez + + val one_cent : tez + + val fifty_cents : tez + + val one : tez + + val ( -? ) : tez -> tez -> tez tzresult + + val ( +? ) : tez -> tez -> tez tzresult + + val ( *? ) : tez -> int64 -> tez tzresult + + val ( /? ) : tez -> int64 -> tez tzresult + + val of_string : string -> tez option + + val to_string : tez -> string + + val of_mutez : int64 -> tez option + + val to_mutez : tez -> int64 + + val of_mutez_exn : int64 -> t + + val mul_exn : t -> int -> t +end + +module Period : sig + include BASIC_DATA + + type period = t + + val rpc_arg : period RPC_arg.arg + + val of_seconds : int64 -> period tzresult + + val of_seconds_exn : int64 -> period + + val to_seconds : period -> int64 + + val mult : int32 -> period -> period tzresult + + val zero : period + + val one_second : period + + val one_minute : period + + val one_hour : period +end + +module Timestamp : sig + include BASIC_DATA with type t = Time.t + + type time = t + + val ( +? ) : time -> Period.t -> time tzresult + + val ( -? ) : time -> time -> Period.t tzresult + + val of_notation : string -> time option + + val to_notation : time -> string + + val of_seconds_string : string -> time option + + val to_seconds_string : time -> string + + val current : context -> time +end + +module Raw_level : sig + include BASIC_DATA + + type raw_level = t + + val rpc_arg : raw_level RPC_arg.arg + + val diff : raw_level -> raw_level -> int32 + + val root : raw_level + + val succ : raw_level -> raw_level + + val pred : raw_level -> raw_level option + + val to_int32 : raw_level -> int32 + + val of_int32 : int32 -> raw_level tzresult +end + +module Cycle : sig + include BASIC_DATA + + type cycle = t + + val rpc_arg : cycle RPC_arg.arg + + val root : cycle + + val succ : cycle -> cycle + + val pred : cycle -> cycle option + + val add : cycle -> int -> cycle + + val sub : cycle -> int -> cycle option + + val to_int32 : cycle -> int32 + + module Map : S.MAP with type key = cycle +end + +module Gas : sig + module Arith : Fixed_point_repr.Safe + + type t = private Unaccounted | Limited of {remaining : Arith.fp} + + val encoding : t Data_encoding.encoding + + val pp : Format.formatter -> t -> unit + + type cost + + val cost_encoding : cost Data_encoding.encoding + + val pp_cost : Format.formatter -> cost -> unit + + type error += Block_quota_exceeded (* `Temporary *) + + type error += Operation_quota_exceeded (* `Temporary *) + + type error += Gas_limit_too_high (* `Permanent *) + + val free : cost + + val atomic_step_cost : 'a Saturation_repr.t -> cost + + val step_cost : 'a Saturation_repr.t -> cost + + val alloc_cost : 'a Saturation_repr.t -> cost + + val alloc_bytes_cost : int -> cost + + val alloc_mbytes_cost : int -> cost + + val read_bytes_cost : int -> cost + + val write_bytes_cost : int -> cost + + val ( *@ ) : 'a Saturation_repr.t -> cost -> cost + + val ( +@ ) : cost -> cost -> cost + + val check_limit : context -> 'a Arith.t -> unit tzresult + + val set_limit : context -> 'a Arith.t -> context + + val set_unlimited : context -> context + + val consume : context -> cost -> context tzresult + + val check_enough : context -> cost -> unit tzresult + + val level : context -> t + + val consumed : since:context -> until:context -> Arith.fp + + val block_level : context -> Arith.fp + + val cost_of_repr : Gas_limit_repr.cost -> cost +end + +module Script_int : module type of Script_int_repr + +module Script_timestamp : sig + open Script_int + + type t + + val compare : t -> t -> int + + val to_string : t -> string + + val to_notation : t -> string option + + val to_num_str : t -> string + + val of_string : string -> t option + + val diff : t -> t -> z num + + val add_delta : t -> z num -> t + + val sub_delta : t -> z num -> t + + val now : context -> t + + val to_zint : t -> Z.t + + val of_zint : Z.t -> t +end + +module Script : sig + type prim = Michelson_v1_primitives.prim = + | K_parameter + | K_storage + | K_code + | D_False + | D_Elt + | D_Left + | D_None + | D_Pair + | D_Right + | D_Some + | D_True + | D_Unit + | I_PACK + | I_UNPACK + | I_BLAKE2B + | I_SHA256 + | I_SHA512 + | I_ABS + | I_ADD + | I_AMOUNT + | I_AND + | I_BALANCE + | I_CAR + | I_CDR + | I_CHAIN_ID + | I_CHECK_SIGNATURE + | I_COMPARE + | I_CONCAT + | I_CONS + | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT + | I_IMPLICIT_ACCOUNT + | I_DIP + | I_DROP + | I_DUP + | I_EDIV + | I_EMPTY_BIG_MAP + | I_EMPTY_MAP + | I_EMPTY_SET + | I_EQ + | I_EXEC + | I_APPLY + | I_FAILWITH + | I_GE + | I_GET + | I_GET_AND_UPDATE + | I_GT + | I_HASH_KEY + | I_IF + | I_IF_CONS + | I_IF_LEFT + | I_IF_NONE + | I_INT + | I_LAMBDA + | I_LE + | I_LEFT + | I_LEVEL + | I_LOOP + | I_LSL + | I_LSR + | I_LT + | I_MAP + | I_MEM + | I_MUL + | I_NEG + | I_NEQ + | I_NIL + | I_NONE + | I_NOT + | I_NOW + | I_OR + | I_PAIR + | I_UNPAIR + | I_PUSH + | I_RIGHT + | I_SIZE + | I_SOME + | I_SOURCE + | I_SENDER + | I_SELF + | I_SELF_ADDRESS + | I_SLICE + | I_STEPS_TO_QUOTA + | I_SUB + | I_SWAP + | I_TRANSFER_TOKENS + | I_SET_DELEGATE + | I_UNIT + | I_UPDATE + | I_XOR + | I_ITER + | I_LOOP_LEFT + | I_ADDRESS + | I_CONTRACT + | I_ISNAT + | I_CAST + | I_RENAME + | I_SAPLING_EMPTY_STATE + | I_SAPLING_VERIFY_UPDATE + | I_DIG + | I_DUG + | I_NEVER + | I_VOTING_POWER + | I_TOTAL_VOTING_POWER + | I_KECCAK + | I_SHA3 + | I_PAIRING_CHECK + | I_TICKET + | I_READ_TICKET + | I_SPLIT_TICKET + | I_JOIN_TICKETS + | T_bool + | T_contract + | T_int + | T_key + | T_key_hash + | T_lambda + | T_list + | T_map + | T_big_map + | T_nat + | T_option + | T_or + | T_pair + | T_set + | T_signature + | T_string + | T_bytes + | T_mutez + | T_timestamp + | T_unit + | T_operation + | T_address + | T_sapling_transaction + | T_sapling_state + | T_chain_id + | T_never + | T_bls12_381_g1 + | T_bls12_381_g2 + | T_bls12_381_fr + | T_ticket + + type location = Micheline.canonical_location + + type annot = Micheline.annot + + type expr = prim Micheline.canonical + + type lazy_expr = expr Data_encoding.lazy_t + + val lazy_expr : expr -> lazy_expr + + type node = (location, prim) Micheline.node + + type t = {code : lazy_expr; storage : lazy_expr} + + val location_encoding : location Data_encoding.t + + val expr_encoding : expr Data_encoding.t + + val prim_encoding : prim Data_encoding.t + + val encoding : t Data_encoding.t + + val lazy_expr_encoding : lazy_expr Data_encoding.t + + val deserialized_cost : expr -> Gas.cost + + val serialized_cost : bytes -> Gas.cost + + val traversal_cost : node -> Gas.cost + + val int_node_cost : Z.t -> Gas.cost + + val int_node_cost_of_numbits : int -> Gas.cost + + val string_node_cost : string -> Gas.cost + + val string_node_cost_of_length : int -> Gas.cost + + val bytes_node_cost : bytes -> Gas.cost + + val bytes_node_cost_of_length : int -> Gas.cost + + val prim_node_cost_nonrec : expr list -> annot -> Gas.cost + + val seq_node_cost_nonrec : expr list -> Gas.cost + + val seq_node_cost_nonrec_of_length : int -> Gas.cost + + val minimal_deserialize_cost : lazy_expr -> Gas.cost + + val force_decode_in_context : + context -> lazy_expr -> (expr * context) tzresult + + val force_bytes_in_context : + context -> lazy_expr -> (bytes * context) tzresult + + val unit_parameter : lazy_expr + + val micheline_nodes : node -> int + + val strip_locations_cost : node -> Gas.cost +end + +module Constants : sig + (** Fixed constants *) + type fixed = { + proof_of_work_nonce_size : int; + nonce_length : int; + max_anon_ops_per_block : int; + max_operation_data_length : int; + max_proposals_per_delegate : int; + } + + val fixed_encoding : fixed Data_encoding.t + + val fixed : fixed + + val proof_of_work_nonce_size : int + + val nonce_length : int + + val max_anon_ops_per_block : int + + val max_operation_data_length : int + + val max_proposals_per_delegate : int + + (** Constants parameterized by context *) + type parametric = { + preserved_cycles : int; + blocks_per_cycle : int32; + blocks_per_commitment : int32; + blocks_per_roll_snapshot : int32; + blocks_per_voting_period : int32; + time_between_blocks : Period.t list; + endorsers_per_block : int; + hard_gas_limit_per_operation : Gas.Arith.integral; + hard_gas_limit_per_block : Gas.Arith.integral; + proof_of_work_threshold : int64; + tokens_per_roll : Tez.t; + michelson_maximum_type_size : int; + seed_nonce_revelation_tip : Tez.t; + origination_size : int; + block_security_deposit : Tez.t; + endorsement_security_deposit : Tez.t; + baking_reward_per_endorsement : Tez.t list; + endorsement_reward : Tez.t list; + cost_per_byte : Tez.t; + hard_storage_limit_per_operation : Z.t; + quorum_min : int32; + quorum_max : int32; + min_proposal_quorum : int32; + initial_endorsers : int; + delay_per_missing_endorsement : Period.t; + } + + val parametric_encoding : parametric Data_encoding.t + + val parametric : context -> parametric + + val preserved_cycles : context -> int + + val blocks_per_cycle : context -> int32 + + val blocks_per_commitment : context -> int32 + + val blocks_per_roll_snapshot : context -> int32 + + val blocks_per_voting_period : context -> int32 + + val time_between_blocks : context -> Period.t list + + val endorsers_per_block : context -> int + + val initial_endorsers : context -> int + + val delay_per_missing_endorsement : context -> Period.t + + val hard_gas_limit_per_operation : context -> Gas.Arith.integral + + val hard_gas_limit_per_block : context -> Gas.Arith.integral + + val cost_per_byte : context -> Tez.t + + val hard_storage_limit_per_operation : context -> Z.t + + val proof_of_work_threshold : context -> int64 + + val tokens_per_roll : context -> Tez.t + + val michelson_maximum_type_size : context -> int + + val baking_reward_per_endorsement : context -> Tez.t list + + val endorsement_reward : context -> Tez.t list + + val seed_nonce_revelation_tip : context -> Tez.t + + val origination_size : context -> int + + val block_security_deposit : context -> Tez.t + + val endorsement_security_deposit : context -> Tez.t + + val quorum_min : context -> int32 + + val quorum_max : context -> int32 + + val min_proposal_quorum : context -> int32 + + (** All constants: fixed and parametric *) + type t = {fixed : fixed; parametric : parametric} + + val encoding : t Data_encoding.t +end + +module Level : sig + type t = private { + level : Raw_level.t; + level_position : int32; + cycle : Cycle.t; + cycle_position : int32; + expected_commitment : bool; + } + + include BASIC_DATA with type t := t + + val pp_full : Format.formatter -> t -> unit + + type level = t + + val root : context -> level + + val succ : context -> level -> level + + val pred : context -> level -> level option + + val from_raw : context -> ?offset:int32 -> Raw_level.t -> level + + val diff : level -> level -> int32 + + val current : context -> level + + val last_level_in_cycle : context -> Cycle.t -> level + + val levels_in_cycle : context -> Cycle.t -> level list + + val levels_in_current_cycle : context -> ?offset:int32 -> unit -> level list + + val last_allowed_fork_level : context -> Raw_level.t + + type compat_t = { + level : Raw_level.t; + level_position : int32; + cycle : Cycle.t; + cycle_position : int32; + voting_period : int32; + voting_period_position : int32; + expected_commitment : bool; + } + + val compat_encoding : compat_t Data_encoding.t + + val to_deprecated_type : + t -> voting_period_index:int32 -> voting_period_position:int32 -> compat_t +end + +module Fitness : sig + include module type of Fitness + + type fitness = t + + val increase : context -> context + + val current : context -> int64 + + val to_int64 : fitness -> int64 tzresult + + val from_int64 : int64 -> bytes list +end + +module Nonce : sig + type t + + type nonce = t + + val encoding : nonce Data_encoding.t + + type unrevealed = { + nonce_hash : Nonce_hash.t; + delegate : public_key_hash; + rewards : Tez.t; + fees : Tez.t; + } + + val record_hash : context -> unrevealed -> context tzresult Lwt.t + + val reveal : context -> Level.t -> nonce -> context tzresult Lwt.t + + type status = Unrevealed of unrevealed | Revealed of nonce + + val get : context -> Level.t -> status tzresult Lwt.t + + val of_bytes : bytes -> nonce tzresult + + val hash : nonce -> Nonce_hash.t + + val check_hash : nonce -> Nonce_hash.t -> bool +end + +module Seed : sig + type seed + + type error += + | Unknown of {oldest : Cycle.t; cycle : Cycle.t; latest : Cycle.t} + + val for_cycle : context -> Cycle.t -> seed tzresult Lwt.t + + val cycle_end : + context -> Cycle.t -> (context * Nonce.unrevealed list) tzresult Lwt.t + + val seed_encoding : seed Data_encoding.t +end + +module Big_map : sig + module Id : sig + type t + + val encoding : t Data_encoding.t + + val rpc_arg : t RPC_arg.arg + + (** In the protocol, to be used in parse_data only *) + val parse_z : Z.t -> t + + (** In the protocol, to be used in unparse_data only *) + val unparse_to_z : t -> Z.t + end + + val fresh : temporary:bool -> context -> (context * Id.t) tzresult Lwt.t + + val mem : + context -> Id.t -> Script_expr_hash.t -> (context * bool) tzresult Lwt.t + + val get_opt : + context -> + Id.t -> + Script_expr_hash.t -> + (context * Script.expr option) tzresult Lwt.t + + val exists : + context -> + Id.t -> + (context * (Script.expr * Script.expr) option) tzresult Lwt.t + + type update = { + key : Script_repr.expr; + key_hash : Script_expr_hash.t; + value : Script_repr.expr option; + } + + type updates = update list + + type alloc = {key_type : Script_repr.expr; value_type : Script_repr.expr} +end + +module Sapling : sig + module Id : sig + type t + + val encoding : t Data_encoding.t + + val rpc_arg : t RPC_arg.arg + + val parse_z : Z.t -> t (* To be used in parse_data only *) + + val unparse_to_z : t -> Z.t (* To be used in unparse_data only *) + end + + val fresh : temporary:bool -> context -> (context * Id.t) tzresult Lwt.t + + type diff = private { + commitments_and_ciphertexts : + (Sapling.Commitment.t * Sapling.Ciphertext.t) list; + nullifiers : Sapling.Nullifier.t list; + } + + val diff_encoding : diff Data_encoding.t + + module Memo_size : sig + type t + + val encoding : t Data_encoding.t + + val equal : t -> t -> bool + + val parse_z : Z.t -> (t, string) result + + val unparse_to_z : t -> Z.t + end + + type state = private {id : Id.t option; diff : diff; memo_size : Memo_size.t} + + (** + Returns a [state] with fields filled accordingly. + [id] should only be used by [extract_lazy_storage_updates]. + *) + val empty_state : ?id:Id.t -> memo_size:Memo_size.t -> unit -> state + + type transaction = Sapling.UTXO.transaction + + val transaction_encoding : transaction Data_encoding.t + + val transaction_get_memo_size : transaction -> Memo_size.t option + + (** + Tries to fetch a state from the storage. + *) + val state_from_id : context -> Id.t -> (state * context) tzresult Lwt.t + + val rpc_arg : Id.t RPC_arg.t + + type root = Sapling.Hash.t + + val root_encoding : root Data_encoding.t + + (* Function exposed as RPC. Returns the root and a diff of a state starting + from an optional offset which is zero by default. *) + val get_diff : + context -> + Id.t -> + ?offset_commitment:Int64.t -> + ?offset_nullifier:Int64.t -> + unit -> + (root * diff) tzresult Lwt.t + + val verify_update : + context -> + state -> + transaction -> + string -> + (context * (Int64.t * state) option) tzresult Lwt.t + + type alloc = {memo_size : Memo_size.t} + + type updates = diff +end + +module Lazy_storage : sig + module Kind : sig + type ('id, 'alloc, 'updates) t = + | Big_map : (Big_map.Id.t, Big_map.alloc, Big_map.updates) t + | Sapling_state : (Sapling.Id.t, Sapling.alloc, Sapling.updates) t + end + + module IdSet : sig + type t + + type 'acc fold_f = { + f : 'i 'a 'u. ('i, 'a, 'u) Kind.t -> 'i -> 'acc -> 'acc; + } + + val empty : t + + val mem : ('i, 'a, 'u) Kind.t -> 'i -> t -> bool + + val add : ('i, 'a, 'u) Kind.t -> 'i -> t -> t + + val diff : t -> t -> t + + val fold : ('i, 'a, 'u) Kind.t -> ('i -> 'acc -> 'acc) -> t -> 'acc -> 'acc + + val fold_all : 'acc fold_f -> t -> 'acc -> 'acc + end + + type ('id, 'alloc) init = Existing | Copy of {src : 'id} | Alloc of 'alloc + + type ('id, 'alloc, 'updates) diff = + | Remove + | Update of {init : ('id, 'alloc) init; updates : 'updates} + + type diffs_item + + val make : ('i, 'a, 'u) Kind.t -> 'i -> ('i, 'a, 'u) diff -> diffs_item + + type diffs = diffs_item list + + val encoding : diffs Data_encoding.t + + val legacy_big_map_diff_encoding : diffs Data_encoding.t + + val cleanup_temporaries : context -> context Lwt.t + + val apply : t -> diffs -> (t * Z.t) tzresult Lwt.t +end + +module Contract : sig + include BASIC_DATA + + type contract = t + + val rpc_arg : contract RPC_arg.arg + + val to_b58check : contract -> string + + val of_b58check : string -> contract tzresult + + val implicit_contract : public_key_hash -> contract + + val is_implicit : contract -> public_key_hash option + + val exists : context -> contract -> bool tzresult Lwt.t + + val must_exist : context -> contract -> unit tzresult Lwt.t + + val allocated : context -> contract -> bool tzresult Lwt.t + + val must_be_allocated : context -> contract -> unit tzresult Lwt.t + + val list : context -> contract list Lwt.t + + val get_manager_key : context -> public_key_hash -> public_key tzresult Lwt.t + + val is_manager_key_revealed : + context -> public_key_hash -> bool tzresult Lwt.t + + val reveal_manager_key : + context -> public_key_hash -> public_key -> context tzresult Lwt.t + + val get_script_code : + context -> contract -> (context * Script.lazy_expr option) tzresult Lwt.t + + val get_script : + context -> contract -> (context * Script.t option) tzresult Lwt.t + + val get_storage : + context -> contract -> (context * Script.expr option) tzresult Lwt.t + + val get_counter : context -> public_key_hash -> Z.t tzresult Lwt.t + + val get_balance : context -> contract -> Tez.t tzresult Lwt.t + + val get_balance_carbonated : + context -> contract -> (context * Tez.t) tzresult Lwt.t + + val init_origination_nonce : context -> Operation_hash.t -> context + + val unset_origination_nonce : context -> context + + val fresh_contract_from_current_nonce : context -> (context * t) tzresult + + val originated_from_current_nonce : + since:context -> until:context -> contract list tzresult Lwt.t + + module Legacy_big_map_diff : sig + type item = private + | Update of { + big_map : Z.t; + diff_key : Script.expr; + diff_key_hash : Script_expr_hash.t; + diff_value : Script.expr option; + } + | Clear of Z.t + | Copy of {src : Z.t; dst : Z.t} + | Alloc of { + big_map : Z.t; + key_type : Script.expr; + value_type : Script.expr; + } + + type t = private item list + + val of_lazy_storage_diff : Lazy_storage.diffs -> t + end + + val originate : + context -> + contract -> + balance:Tez.t -> + script:Script.t * Lazy_storage.diffs option -> + delegate:public_key_hash option -> + context tzresult Lwt.t + + type error += Balance_too_low of contract * Tez.t * Tez.t + + val spend : context -> contract -> Tez.t -> context tzresult Lwt.t + + val credit : context -> contract -> Tez.t -> context tzresult Lwt.t + + val update_script_storage : + context -> + contract -> + Script.expr -> + Lazy_storage.diffs option -> + context tzresult Lwt.t + + val used_storage_space : context -> t -> Z.t tzresult Lwt.t + + val increment_counter : context -> public_key_hash -> context tzresult Lwt.t + + val check_counter_increment : + context -> public_key_hash -> Z.t -> unit tzresult Lwt.t + + (**/**) + + (* Only for testing *) + type origination_nonce + + val initial_origination_nonce : Operation_hash.t -> origination_nonce + + val originated_contract : origination_nonce -> contract +end + +module Receipt : sig + type balance = + | Contract of Contract.t + | Rewards of Signature.Public_key_hash.t * Cycle.t + | Fees of Signature.Public_key_hash.t * Cycle.t + | Deposits of Signature.Public_key_hash.t * Cycle.t + + type balance_update = Debited of Tez.t | Credited of Tez.t + + type update_origin = Block_application | Protocol_migration + + type balance_updates = (balance * balance_update * update_origin) list + + val balance_updates_encoding : balance_updates Data_encoding.t + + val cleanup_balance_updates : balance_updates -> balance_updates +end + +module Delegate : sig + val get : context -> Contract.t -> public_key_hash option tzresult Lwt.t + + val set : + context -> Contract.t -> public_key_hash option -> context tzresult Lwt.t + + val fold : + context -> init:'a -> f:(public_key_hash -> 'a -> 'a Lwt.t) -> 'a Lwt.t + + val list : context -> public_key_hash list Lwt.t + + val freeze_deposit : + context -> public_key_hash -> Tez.t -> context tzresult Lwt.t + + val freeze_rewards : + context -> public_key_hash -> Tez.t -> context tzresult Lwt.t + + val freeze_fees : + context -> public_key_hash -> Tez.t -> context tzresult Lwt.t + + val cycle_end : + context -> + Cycle.t -> + Nonce.unrevealed list -> + (context * Receipt.balance_updates * Signature.Public_key_hash.t list) + tzresult + Lwt.t + + type frozen_balance = {deposit : Tez.t; fees : Tez.t; rewards : Tez.t} + + val punish : + context -> + public_key_hash -> + Cycle.t -> + (context * frozen_balance) tzresult Lwt.t + + val full_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t + + val has_frozen_balance : + context -> public_key_hash -> Cycle.t -> bool tzresult Lwt.t + + val frozen_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t + + val frozen_balance_encoding : frozen_balance Data_encoding.t + + val frozen_balance_by_cycle_encoding : + frozen_balance Cycle.Map.t Data_encoding.t + + val frozen_balance_by_cycle : + context -> Signature.Public_key_hash.t -> frozen_balance Cycle.Map.t Lwt.t + + val staking_balance : + context -> Signature.Public_key_hash.t -> Tez.t tzresult Lwt.t + + val delegated_contracts : + context -> Signature.Public_key_hash.t -> Contract.t list Lwt.t + + val delegated_balance : + context -> Signature.Public_key_hash.t -> Tez.t tzresult Lwt.t + + val deactivated : + context -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + + val grace_period : + context -> Signature.Public_key_hash.t -> Cycle.t tzresult Lwt.t +end + +module Voting_period : sig + type kind = Proposal | Exploration | Cooldown | Promotion | Adoption + + val kind_encoding : kind Data_encoding.encoding + + val pp_kind : Format.formatter -> kind -> unit + + (* This type should be abstract *) + type voting_period = private { + index : int32; + kind : kind; + start_position : int32; + } + + type t = voting_period + + include BASIC_DATA with type t := t + + val encoding : voting_period Data_encoding.t + + val pp : Format.formatter -> voting_period -> unit + + val reset : context -> context tzresult Lwt.t + + val succ : context -> context tzresult Lwt.t + + val get_current : context -> voting_period tzresult Lwt.t + + val get_current_kind : context -> kind tzresult Lwt.t + + val is_last_block : context -> bool tzresult Lwt.t + + type info = {voting_period : t; position : int32; remaining : int32} + + val info_encoding : info Data_encoding.t + + val pp_info : Format.formatter -> info -> unit + + val get_current_info : context -> info tzresult Lwt.t + + val get_rpc_fixed_current_info : context -> info tzresult Lwt.t + + val get_rpc_fixed_succ_info : context -> info tzresult Lwt.t +end + +module Vote : sig + type proposal = Protocol_hash.t + + val record_proposal : + context -> Protocol_hash.t -> public_key_hash -> context tzresult Lwt.t + + val get_proposals : context -> int32 Protocol_hash.Map.t tzresult Lwt.t + + val clear_proposals : context -> context Lwt.t + + val recorded_proposal_count_for_delegate : + context -> public_key_hash -> int tzresult Lwt.t + + val listings_encoding : + (Signature.Public_key_hash.t * int32) list Data_encoding.t + + val update_listings : context -> context tzresult Lwt.t + + val listing_size : context -> int32 tzresult Lwt.t + + val in_listings : context -> public_key_hash -> bool Lwt.t + + val get_listings : context -> (public_key_hash * int32) list Lwt.t + + type ballot = Yay | Nay | Pass + + val get_voting_power_free : + context -> Signature.Public_key_hash.t -> int32 tzresult Lwt.t + + val get_voting_power : + context -> Signature.Public_key_hash.t -> (context * int32) tzresult Lwt.t + + val get_total_voting_power_free : context -> int32 tzresult Lwt.t + + val get_total_voting_power : context -> (context * int32) tzresult Lwt.t + + val ballot_encoding : ballot Data_encoding.t + + type ballots = {yay : int32; nay : int32; pass : int32} + + val ballots_encoding : ballots Data_encoding.t + + val has_recorded_ballot : context -> public_key_hash -> bool Lwt.t + + val record_ballot : + context -> public_key_hash -> ballot -> context tzresult Lwt.t + + val get_ballots : context -> ballots tzresult Lwt.t + + val get_ballot_list : + context -> (Signature.Public_key_hash.t * ballot) list Lwt.t + + val clear_ballots : context -> context Lwt.t + + val get_current_quorum : context -> int32 tzresult Lwt.t + + val get_participation_ema : context -> int32 tzresult Lwt.t + + val set_participation_ema : context -> int32 -> context tzresult Lwt.t + + val get_current_proposal : context -> proposal tzresult Lwt.t + + val find_current_proposal : context -> proposal option tzresult Lwt.t + + val init_current_proposal : context -> proposal -> context tzresult Lwt.t + + val clear_current_proposal : context -> context tzresult Lwt.t +end + +module Block_header : sig + type contents = { + priority : int; + seed_nonce_hash : Nonce_hash.t option; + proof_of_work_nonce : bytes; + } + + type protocol_data = {contents : contents; signature : Signature.t} + + type t = {shell : Block_header.shell_header; protocol_data : protocol_data} + + type block_header = t + + type raw = Block_header.t + + type shell_header = Block_header.shell_header + + val raw : block_header -> raw + + val hash : block_header -> Block_hash.t + + val hash_raw : raw -> Block_hash.t + + val encoding : block_header Data_encoding.encoding + + val raw_encoding : raw Data_encoding.t + + val contents_encoding : contents Data_encoding.t + + val unsigned_encoding : (shell_header * contents) Data_encoding.t + + val protocol_data_encoding : protocol_data Data_encoding.encoding + + val shell_header_encoding : shell_header Data_encoding.encoding + + (** The maximum size of block headers in bytes *) + val max_header_length : int +end + +module Kind : sig + type seed_nonce_revelation = Seed_nonce_revelation_kind + + type endorsement_with_slot = Endorsement_with_slot_kind + + type double_endorsement_evidence = Double_endorsement_evidence_kind + + type double_baking_evidence = Double_baking_evidence_kind + + type activate_account = Activate_account_kind + + type endorsement = Endorsement_kind + + type proposals = Proposals_kind + + type ballot = Ballot_kind + + type reveal = Reveal_kind + + type transaction = Transaction_kind + + type origination = Origination_kind + + type delegation = Delegation_kind + + type failing_noop = Failing_noop_kind + + type 'a manager = + | Reveal_manager_kind : reveal manager + | Transaction_manager_kind : transaction manager + | Origination_manager_kind : origination manager + | Delegation_manager_kind : delegation manager +end + +type 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; +} + +and 'kind protocol_data = { + contents : 'kind contents_list; + signature : Signature.t option; +} + +and _ contents_list = + | Single : 'kind contents -> 'kind contents_list + | Cons : + 'kind Kind.manager contents * 'rest Kind.manager contents_list + -> ('kind * 'rest) Kind.manager contents_list + +and _ contents = + | Endorsement : {level : Raw_level.t} -> Kind.endorsement contents + | Seed_nonce_revelation : { + level : Raw_level.t; + nonce : Nonce.t; + } + -> Kind.seed_nonce_revelation contents + | Endorsement_with_slot : { + endorsement : Kind.endorsement operation; + slot : int; + } + -> Kind.endorsement_with_slot contents + | Double_endorsement_evidence : { + op1 : Kind.endorsement operation; + op2 : Kind.endorsement operation; + slot : int; + } + -> Kind.double_endorsement_evidence contents + | Double_baking_evidence : { + bh1 : Block_header.t; + bh2 : Block_header.t; + } + -> Kind.double_baking_evidence contents + | Activate_account : { + id : Ed25519.Public_key_hash.t; + activation_code : Blinded_public_key_hash.activation_code; + } + -> Kind.activate_account contents + | Proposals : { + source : Signature.Public_key_hash.t; + period : int32; + proposals : Protocol_hash.t list; + } + -> Kind.proposals contents + | Ballot : { + source : Signature.Public_key_hash.t; + period : int32; + proposal : Protocol_hash.t; + ballot : Vote.ballot; + } + -> Kind.ballot contents + | Failing_noop : string -> Kind.failing_noop contents + | Manager_operation : { + source : Signature.Public_key_hash.t; + fee : Tez.tez; + counter : counter; + operation : 'kind manager_operation; + gas_limit : Gas.Arith.integral; + storage_limit : Z.t; + } + -> 'kind Kind.manager contents + +and _ manager_operation = + | Reveal : Signature.Public_key.t -> Kind.reveal manager_operation + | Transaction : { + amount : Tez.tez; + parameters : Script.lazy_expr; + entrypoint : string; + destination : Contract.contract; + } + -> Kind.transaction manager_operation + | Origination : { + delegate : Signature.Public_key_hash.t option; + script : Script.t; + credit : Tez.tez; + preorigination : Contract.t option; + } + -> Kind.origination manager_operation + | Delegation : + Signature.Public_key_hash.t option + -> Kind.delegation manager_operation + +and counter = Z.t + +type 'kind internal_operation = { + source : Contract.contract; + operation : 'kind manager_operation; + nonce : int; +} + +type packed_manager_operation = + | Manager : 'kind manager_operation -> packed_manager_operation + +type packed_contents = Contents : 'kind contents -> packed_contents + +type packed_contents_list = + | Contents_list : 'kind contents_list -> packed_contents_list + +type packed_protocol_data = + | Operation_data : 'kind protocol_data -> packed_protocol_data + +type packed_operation = { + shell : Operation.shell_header; + protocol_data : packed_protocol_data; +} + +type packed_internal_operation = + | Internal_operation : 'kind internal_operation -> packed_internal_operation + +val manager_kind : 'kind manager_operation -> 'kind Kind.manager + +module Fees : sig + val origination_burn : context -> (context * Tez.t) tzresult + + val record_paid_storage_space : + context -> Contract.t -> (context * Z.t * Z.t * Tez.t) tzresult Lwt.t + + val start_counting_storage_fees : context -> context + + val burn_storage_fees : + context -> storage_limit:Z.t -> payer:Contract.t -> context tzresult Lwt.t + + type error += Cannot_pay_storage_fee (* `Temporary *) + + type error += Operation_quota_exceeded (* `Temporary *) + + type error += Storage_limit_too_high (* `Permanent *) + + val check_storage_limit : context -> storage_limit:Z.t -> unit tzresult +end + +module Operation : sig + type nonrec 'kind contents = 'kind contents + + type nonrec packed_contents = packed_contents + + val contents_encoding : packed_contents Data_encoding.t + + type nonrec 'kind protocol_data = 'kind protocol_data + + type nonrec packed_protocol_data = packed_protocol_data + + val protocol_data_encoding : packed_protocol_data Data_encoding.t + + val unsigned_encoding : + (Operation.shell_header * packed_contents_list) Data_encoding.t + + type raw = Operation.t = {shell : Operation.shell_header; proto : bytes} + + val raw_encoding : raw Data_encoding.t + + val contents_list_encoding : packed_contents_list Data_encoding.t + + type 'kind t = 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; + } + + type nonrec packed = packed_operation + + val encoding : packed Data_encoding.t + + val raw : _ operation -> raw + + val hash : _ operation -> Operation_hash.t + + val hash_raw : raw -> Operation_hash.t + + val hash_packed : packed_operation -> Operation_hash.t + + val acceptable_passes : packed_operation -> int list + + type error += Missing_signature (* `Permanent *) + + type error += Invalid_signature (* `Permanent *) + + val check_signature : + public_key -> Chain_id.t -> _ operation -> unit tzresult + + val internal_operation_encoding : packed_internal_operation Data_encoding.t + + val pack : 'kind operation -> packed_operation + + type ('a, 'b) eq = Eq : ('a, 'a) eq + + val equal : 'a operation -> 'b operation -> ('a, 'b) eq option + + module Encoding : sig + type 'b case = + | Case : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_contents -> 'b contents option; + proj : 'b contents -> 'a; + inj : 'a -> 'b contents; + } + -> 'b case + + val endorsement_case : Kind.endorsement case + + val seed_nonce_revelation_case : Kind.seed_nonce_revelation case + + val endorsement_with_slot_case : Kind.endorsement_with_slot case + + val double_endorsement_evidence_case : + Kind.double_endorsement_evidence case + + val double_baking_evidence_case : Kind.double_baking_evidence case + + val activate_account_case : Kind.activate_account case + + val proposals_case : Kind.proposals case + + val ballot_case : Kind.ballot case + + val failing_noop_case : Kind.failing_noop case + + val reveal_case : Kind.reveal Kind.manager case + + val transaction_case : Kind.transaction Kind.manager case + + val origination_case : Kind.origination Kind.manager case + + val delegation_case : Kind.delegation Kind.manager case + + module Manager_operations : sig + type 'b case = + | MCase : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : + packed_manager_operation -> 'kind manager_operation option; + proj : 'kind manager_operation -> 'a; + inj : 'a -> 'kind manager_operation; + } + -> 'kind case + + val reveal_case : Kind.reveal case + + val transaction_case : Kind.transaction case + + val origination_case : Kind.origination case + + val delegation_case : Kind.delegation case + end + end + + val of_list : packed_contents list -> packed_contents_list + + val to_list : packed_contents_list -> packed_contents list +end + +module Roll : sig + type t = private int32 + + type roll = t + + val encoding : roll Data_encoding.t + + val snapshot_rolls : context -> context tzresult Lwt.t + + val cycle_end : context -> Cycle.t -> context tzresult Lwt.t + + val baking_rights_owner : + context -> Level.t -> priority:int -> public_key tzresult Lwt.t + + val endorsement_rights_owner : + context -> Level.t -> slot:int -> public_key tzresult Lwt.t + + val delegate_pubkey : context -> public_key_hash -> public_key tzresult Lwt.t + + val count_rolls : + context -> Signature.Public_key_hash.t -> int tzresult Lwt.t + + val get_change : + context -> Signature.Public_key_hash.t -> Tez.t tzresult Lwt.t +end + +module Commitment : sig + type t = { + blinded_public_key_hash : Blinded_public_key_hash.t; + amount : Tez.tez; + } + + val encoding : t Data_encoding.t + + val find : + context -> Blinded_public_key_hash.t -> Tez.t option tzresult Lwt.t + + val remove_existing : + context -> Blinded_public_key_hash.t -> context tzresult Lwt.t +end + +module Bootstrap : sig + val cycle_end : context -> Cycle.t -> context tzresult Lwt.t +end + +module Global : sig + val get_block_priority : context -> int tzresult Lwt.t + + val set_block_priority : context -> int -> context tzresult Lwt.t +end + +val prepare_first_block : + Context.t -> + typecheck:(context -> + Script.t -> + ((Script.t * Lazy_storage.diffs option) * context) tzresult Lwt.t) -> + level:Int32.t -> + timestamp:Time.t -> + fitness:Fitness.t -> + context tzresult Lwt.t + +val prepare : + Context.t -> + level:Int32.t -> + predecessor_timestamp:Time.t -> + timestamp:Time.t -> + fitness:Fitness.t -> + (context * Receipt.balance_updates) tzresult Lwt.t + +val finalize : ?commit_message:string -> context -> Updater.validation_result + +val activate : context -> Protocol_hash.t -> context Lwt.t + +val record_endorsement : context -> Signature.Public_key_hash.t -> context + +val allowed_endorsements : + context -> + (Signature.Public_key.t * int list * bool) Signature.Public_key_hash.Map.t + +val init_endorsements : + context -> + (Signature.Public_key.t * int list * bool) Signature.Public_key_hash.Map.t -> + context + +val included_endorsements : context -> int + +val reset_internal_nonce : context -> context + +val fresh_internal_nonce : context -> (context * int) tzresult + +val record_internal_nonce : context -> int -> context + +val internal_nonce_already_recorded : context -> int -> bool + +val add_fees : context -> Tez.t -> context tzresult + +val add_rewards : context -> Tez.t -> context tzresult + +val add_deposit : + context -> Signature.Public_key_hash.t -> Tez.t -> context tzresult + +val get_fees : context -> Tez.t + +val get_rewards : context -> Tez.t + +val get_deposits : context -> Tez.t Signature.Public_key_hash.Map.t + +val description : context Storage_description.t + +module Parameters : sig + type bootstrap_account = { + public_key_hash : public_key_hash; + public_key : public_key option; + amount : Tez.t; + } + + type bootstrap_contract = { + delegate : public_key_hash; + amount : Tez.t; + script : Script.t; + } + + type t = { + bootstrap_accounts : bootstrap_account list; + bootstrap_contracts : bootstrap_contract list; + commitments : Commitment.t list; + constants : Constants.parametric; + security_deposit_ramp_up_cycles : int option; + no_reward_cycles : int option; + } + + val encoding : t Data_encoding.t +end diff --git a/src/proto_009_PsFLoren/lib_protocol/alpha_services.ml b/src/proto_009_PsFLoren/lib_protocol/alpha_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..c774f0c74215eb6258bf70b55daefafee125d3c6 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/alpha_services.ml @@ -0,0 +1,120 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let custom_root = RPC_path.open_root + +module Seed = struct + module S = struct + open Data_encoding + + let seed = + RPC_service.post_service + ~description:"Seed of the cycle to which the block belongs." + ~query:RPC_query.empty + ~input:empty + ~output:Seed.seed_encoding + RPC_path.(custom_root / "context" / "seed") + end + + let () = + let open Services_registration in + register0 S.seed (fun ctxt () () -> + let l = Level.current ctxt in + Seed.for_cycle ctxt l.cycle) + + let get ctxt block = RPC_context.make_call0 S.seed ctxt block () () +end + +module Nonce = struct + type info = Revealed of Nonce.t | Missing of Nonce_hash.t | Forgotten + + let info_encoding = + let open Data_encoding in + union + [ case + (Tag 0) + ~title:"Revealed" + (obj1 (req "nonce" Nonce.encoding)) + (function Revealed nonce -> Some nonce | _ -> None) + (fun nonce -> Revealed nonce); + case + (Tag 1) + ~title:"Missing" + (obj1 (req "hash" Nonce_hash.encoding)) + (function Missing nonce -> Some nonce | _ -> None) + (fun nonce -> Missing nonce); + case + (Tag 2) + ~title:"Forgotten" + empty + (function Forgotten -> Some () | _ -> None) + (fun () -> Forgotten) ] + + module S = struct + let get = + RPC_service.get_service + ~description:"Info about the nonce of a previous block." + ~query:RPC_query.empty + ~output:info_encoding + RPC_path.(custom_root / "context" / "nonces" /: Raw_level.rpc_arg) + end + + let register () = + let open Services_registration in + register1 S.get (fun ctxt raw_level () () -> + let level = Level.from_raw ctxt raw_level in + Nonce.get ctxt level + >|= function + | Ok (Revealed nonce) -> + ok (Revealed nonce) + | Ok (Unrevealed {nonce_hash; _}) -> + ok (Missing nonce_hash) + | Error _ -> + ok Forgotten) + + let get ctxt block level = + RPC_context.make_call1 S.get ctxt block level () () +end + +module Contract = Contract_services +module Constants = Constants_services +module Delegate = Delegate_services +module Helpers = Helpers_services +module Forge = Helpers_services.Forge +module Parse = Helpers_services.Parse +module Voting = Voting_services +module Sapling = Sapling_services + +let register () = + Contract.register () ; + Constants.register () ; + Delegate.register () ; + Helpers.register () ; + Nonce.register () ; + Voting.register () ; + Sapling.register () diff --git a/src/proto_009_PsFLoren/lib_protocol/alpha_services.mli b/src/proto_009_PsFLoren/lib_protocol/alpha_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..7c59bf7f2a18d08464deb75e028f8172dac37953 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/alpha_services.mli @@ -0,0 +1,49 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +module Seed : sig + val get : 'a #RPC_context.simple -> 'a -> Seed.seed shell_tzresult Lwt.t +end + +module Nonce : sig + type info = Revealed of Nonce.t | Missing of Nonce_hash.t | Forgotten + + val get : + 'a #RPC_context.simple -> 'a -> Raw_level.t -> info shell_tzresult Lwt.t +end + +module Contract = Contract_services +module Constants = Constants_services +module Delegate = Delegate_services +module Helpers = Helpers_services +module Forge = Helpers_services.Forge +module Parse = Helpers_services.Parse +module Voting = Voting_services +module Sapling = Sapling_services + +val register : unit -> unit diff --git a/src/proto_009_PsFLoren/lib_protocol/amendment.ml b/src/proto_009_PsFLoren/lib_protocol/amendment.ml new file mode 100644 index 0000000000000000000000000000000000000000..f1ac053f9a7d126fb169664edfbc4d019bcddeba --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/amendment.ml @@ -0,0 +1,298 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** Returns the proposal submitted by the most delegates. + Returns None in case of a tie, if proposal quorum is below required + minimum or if there are no proposals. *) +let select_winning_proposal ctxt = + Vote.get_proposals ctxt + >>=? fun proposals -> + let merge proposal vote winners = + match winners with + | None -> + Some ([proposal], vote) + | Some (winners, winners_vote) as previous -> + if Compare.Int32.(vote = winners_vote) then + Some (proposal :: winners, winners_vote) + else if Compare.Int32.(vote > winners_vote) then Some ([proposal], vote) + else previous + in + match Protocol_hash.Map.fold merge proposals None with + | Some ([proposal], vote) -> + Vote.listing_size ctxt + >>=? fun max_vote -> + let min_proposal_quorum = Constants.min_proposal_quorum ctxt in + let min_vote_to_pass = + Int32.div (Int32.mul min_proposal_quorum max_vote) 100_00l + in + if Compare.Int32.(vote >= min_vote_to_pass) then return_some proposal + else return_none + | _ -> + return_none + +(* in case of a tie, let's do nothing. *) + +(** A proposal is approved if it has supermajority and the participation reaches + the current quorum. + Supermajority means the yays are more 8/10 of casted votes. + The participation is the ratio of all received votes, including passes, with + respect to the number of possible votes. + The participation EMA (exponential moving average) uses the last + participation EMA and the current participation./ + The expected quorum is calculated using the last participation EMA, capped + by the min/max quorum protocol constants. *) +let approval_and_participation_ema (ballots : Vote.ballots) ~maximum_vote + ~participation_ema ~expected_quorum = + (* Note overflows: considering a maximum of 8e8 tokens, with roll size as + small as 1e3, there is a maximum of 8e5 rolls and thus votes. + In 'participation' an Int64 is used because in the worst case 'all_votes is + 8e5 and after the multiplication is 8e9, making it potentially overflow a + signed Int32 which is 2e9. *) + let casted_votes = Int32.add ballots.yay ballots.nay in + let all_votes = Int32.add casted_votes ballots.pass in + let supermajority = Int32.div (Int32.mul 8l casted_votes) 10l in + let participation = + (* in centile of percentage *) + Int64.( + to_int32 (div (mul (of_int32 all_votes) 100_00L) (of_int32 maximum_vote))) + in + let approval = + Compare.Int32.( + participation >= expected_quorum && ballots.yay >= supermajority) + in + let new_participation_ema = + Int32.(div (add (mul 8l participation_ema) (mul 2l participation)) 10l) + in + (approval, new_participation_ema) + +let get_approval_and_update_participation_ema ctxt = + Vote.get_ballots ctxt + >>=? fun ballots -> + Vote.listing_size ctxt + >>=? fun maximum_vote -> + Vote.get_participation_ema ctxt + >>=? fun participation_ema -> + Vote.get_current_quorum ctxt + >>=? fun expected_quorum -> + Vote.clear_ballots ctxt + >>= fun ctxt -> + let (approval, new_participation_ema) = + approval_and_participation_ema + ballots + ~maximum_vote + ~participation_ema + ~expected_quorum + in + Vote.set_participation_ema ctxt new_participation_ema + >|=? fun ctxt -> (ctxt, approval) + +(** Implements the state machine of the amendment procedure. Note that + [update_listings], that computes the vote weight of each delegate, is run at + the end of each voting period. This state-machine prepare the voting_period + for the next block. *) +let start_new_voting_period ctxt = + Voting_period.get_current_kind ctxt + >>=? fun kind -> + ( match kind with + | Proposal -> ( + select_winning_proposal ctxt + >>=? fun proposal -> + Vote.clear_proposals ctxt + >>= fun ctxt -> + match proposal with + | None -> + Voting_period.reset ctxt + | Some proposal -> + Vote.init_current_proposal ctxt proposal >>=? Voting_period.succ ) + | Exploration -> + get_approval_and_update_participation_ema ctxt + >>=? fun (ctxt, approved) -> + if approved then Voting_period.succ ctxt + else + Vote.clear_current_proposal ctxt + >>=? fun ctxt -> Voting_period.reset ctxt + | Cooldown -> + Voting_period.succ ctxt + | Promotion -> + get_approval_and_update_participation_ema ctxt + >>=? fun (ctxt, approved) -> + if approved then Voting_period.succ ctxt + else Vote.clear_current_proposal ctxt >>=? Voting_period.reset + | Adoption -> + Vote.get_current_proposal ctxt + >>=? fun proposal -> + activate ctxt proposal + >>= fun ctxt -> Vote.clear_current_proposal ctxt >>=? Voting_period.reset + ) + >>=? fun ctxt -> Vote.update_listings ctxt + +type error += + | (* `Branch *) + Invalid_proposal + | Unexpected_proposal + | Unauthorized_proposal + | Too_many_proposals + | Empty_proposal + | Unexpected_ballot + | Unauthorized_ballot + +let () = + let open Data_encoding in + (* Invalid proposal *) + register_error_kind + `Branch + ~id:"invalid_proposal" + ~title:"Invalid proposal" + ~description:"Ballot provided for a proposal that is not the current one." + ~pp:(fun ppf () -> Format.fprintf ppf "Invalid proposal") + empty + (function Invalid_proposal -> Some () | _ -> None) + (fun () -> Invalid_proposal) ; + (* Unexpected proposal *) + register_error_kind + `Branch + ~id:"unexpected_proposal" + ~title:"Unexpected proposal" + ~description:"Proposal recorded outside of a proposal period." + ~pp:(fun ppf () -> Format.fprintf ppf "Unexpected proposal") + empty + (function Unexpected_proposal -> Some () | _ -> None) + (fun () -> Unexpected_proposal) ; + (* Unauthorized proposal *) + register_error_kind + `Branch + ~id:"unauthorized_proposal" + ~title:"Unauthorized proposal" + ~description: + "The delegate provided for the proposal is not in the voting listings." + ~pp:(fun ppf () -> Format.fprintf ppf "Unauthorized proposal") + empty + (function Unauthorized_proposal -> Some () | _ -> None) + (fun () -> Unauthorized_proposal) ; + (* Unexpected ballot *) + register_error_kind + `Branch + ~id:"unexpected_ballot" + ~title:"Unexpected ballot" + ~description:"Ballot recorded outside of a voting period." + ~pp:(fun ppf () -> Format.fprintf ppf "Unexpected ballot") + empty + (function Unexpected_ballot -> Some () | _ -> None) + (fun () -> Unexpected_ballot) ; + (* Unauthorized ballot *) + register_error_kind + `Branch + ~id:"unauthorized_ballot" + ~title:"Unauthorized ballot" + ~description: + "The delegate provided for the ballot is not in the voting listings." + ~pp:(fun ppf () -> Format.fprintf ppf "Unauthorized ballot") + empty + (function Unauthorized_ballot -> Some () | _ -> None) + (fun () -> Unauthorized_ballot) ; + (* Too many proposals *) + register_error_kind + `Branch + ~id:"too_many_proposals" + ~title:"Too many proposals" + ~description: + "The delegate reached the maximum number of allowed proposals." + ~pp:(fun ppf () -> Format.fprintf ppf "Too many proposals") + empty + (function Too_many_proposals -> Some () | _ -> None) + (fun () -> Too_many_proposals) ; + (* Empty proposal *) + register_error_kind + `Branch + ~id:"empty_proposal" + ~title:"Empty proposal" + ~description:"Proposal lists cannot be empty." + ~pp:(fun ppf () -> Format.fprintf ppf "Empty proposal") + empty + (function Empty_proposal -> Some () | _ -> None) + (fun () -> Empty_proposal) + +(* @return [true] if [List.length l] > [n] w/o computing length *) +let rec longer_than l n = + if Compare.Int.(n < 0) then assert false + else + match l with + | [] -> + false + | _ :: rest -> + if Compare.Int.(n = 0) then true + else (* n > 0 *) + longer_than rest (n - 1) + +let record_proposals ctxt delegate proposals = + (match proposals with [] -> error Empty_proposal | _ :: _ -> ok_unit) + >>?= fun () -> + Voting_period.get_current_kind ctxt + >>=? function + | Proposal -> + Vote.in_listings ctxt delegate + >>= fun in_listings -> + if in_listings then + Vote.recorded_proposal_count_for_delegate ctxt delegate + >>=? fun count -> + error_when + (longer_than proposals (Constants.max_proposals_per_delegate - count)) + Too_many_proposals + >>?= fun () -> + fold_left_s + (fun ctxt proposal -> Vote.record_proposal ctxt proposal delegate) + ctxt + proposals + else fail Unauthorized_proposal + | Exploration | Cooldown | Promotion | Adoption -> + fail Unexpected_proposal + +let record_ballot ctxt delegate proposal ballot = + Voting_period.get_current_kind ctxt + >>=? function + | Exploration | Promotion -> + Vote.get_current_proposal ctxt + >>=? fun current_proposal -> + error_unless + (Protocol_hash.equal proposal current_proposal) + Invalid_proposal + >>?= fun () -> + Vote.has_recorded_ballot ctxt delegate + >>= fun has_ballot -> + error_when has_ballot Unauthorized_ballot + >>?= fun () -> + Vote.in_listings ctxt delegate + >>= fun in_listings -> + if in_listings then Vote.record_ballot ctxt delegate ballot + else fail Unauthorized_ballot + | Cooldown | Proposal | Adoption -> + fail Unexpected_ballot + +let may_start_new_voting_period ctxt = + Voting_period.is_last_block ctxt + >>=? fun is_last -> + if is_last then start_new_voting_period ctxt else return ctxt diff --git a/src/proto_009_PsFLoren/lib_protocol/amendment.mli b/src/proto_009_PsFLoren/lib_protocol/amendment.mli new file mode 100644 index 0000000000000000000000000000000000000000..200019bd03eaef84f09a08188d7c087595288695 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/amendment.mli @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Only delegates with at least one roll take part in the amendment + procedure. It works as follows: + + - Proposal period: delegates can submit protocol amendment + proposals using the proposal operation. At the end of a proposal + period, the proposal with most supporters is selected and we move + to an exploration period. If there are no proposals, or a tie + between proposals, a new proposal period starts. + + - Exploration period: delegates can cast votes to test or not the + winning proposal using the ballot operation. At the end of an + exploration period if participation reaches the quorum and the + proposal has a supermajority in favor, we proceed to a cooldown + period. Otherwise we go back to a proposal period. In any case, if + there is enough participation the quorum is updated. + + - Cooldown period: Nothing happens, this period is only a time gap + between exploration and promotion periods. At the end of a cooldown + period we move to a promotion period. + + - Promotion period: delegates can cast votes to promote or not the + proposal using the ballot operation. At the end of a promotion + period if participation reaches the quorum and the proposal has a + supermajority in favor, we move to an adoption period. Otherwise we + go back to a proposal period. In any case, if there is enough + participation the quorum is updated. + + - Adoption period: At the end of an adoption period, the proposal + is activated as the new protocol. *) + +open Alpha_context + +(** If at the end of a voting period, moves to the next one following + the state machine of the amendment procedure. *) +val may_start_new_voting_period : context -> context tzresult Lwt.t + +type error += + | Unexpected_proposal + | Unauthorized_proposal + | Too_many_proposals + | Empty_proposal + +(** Records a list of proposals for a delegate. + @raise Unexpected_proposal if [ctxt] is not in a proposal period. + @raise Unauthorized_proposal if [delegate] is not in the listing. *) +val record_proposals : + context -> public_key_hash -> Protocol_hash.t list -> context tzresult Lwt.t + +type error += Invalid_proposal | Unexpected_ballot | Unauthorized_ballot + +val record_ballot : + context -> + public_key_hash -> + Protocol_hash.t -> + Vote.ballot -> + context tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/apply.ml b/src/proto_009_PsFLoren/lib_protocol/apply.ml new file mode 100644 index 0000000000000000000000000000000000000000..5289a1a2298e6a3409d43b15ff1ec216e37aa114 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/apply.ml @@ -0,0 +1,1648 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Main Entry Points *) + +open Alpha_context + +type error += Wrong_voting_period of int32 * int32 + +(* `Temporary *) + +type error += Wrong_endorsement_predecessor of Block_hash.t * Block_hash.t + +(* `Temporary *) + +type error += Duplicate_endorsement of Signature.Public_key_hash.t + +(* `Branch *) + +type error += Invalid_endorsement_level + +type error += Invalid_endorsement_wrapper + +type error += Invalid_commitment of {expected : bool} + +type error += Internal_operation_replay of packed_internal_operation + +type error += Invalid_double_endorsement_evidence (* `Permanent *) + +type error += + | Inconsistent_double_endorsement_evidence of { + delegate1 : Signature.Public_key_hash.t; + delegate2 : Signature.Public_key_hash.t; + } + +(* `Permanent *) + +type error += Unwrapped_endorsement (* `Permanent *) + +type error += Unrequired_double_endorsement_evidence (* `Branch*) + +type error += + | Too_early_double_endorsement_evidence of { + level : Raw_level.t; + current : Raw_level.t; + } + +(* `Temporary *) + +type error += + | Outdated_double_endorsement_evidence of { + level : Raw_level.t; + last : Raw_level.t; + } + +(* `Permanent *) + +type error += + | Invalid_double_baking_evidence of { + hash1 : Block_hash.t; + level1 : Int32.t; + hash2 : Block_hash.t; + level2 : Int32.t; + } + +(* `Permanent *) + +type error += + | Inconsistent_double_baking_evidence of { + delegate1 : Signature.Public_key_hash.t; + delegate2 : Signature.Public_key_hash.t; + } + +(* `Permanent *) + +type error += Unrequired_double_baking_evidence (* `Branch*) + +type error += + | Too_early_double_baking_evidence of { + level : Raw_level.t; + current : Raw_level.t; + } + +(* `Temporary *) + +type error += + | Outdated_double_baking_evidence of { + level : Raw_level.t; + last : Raw_level.t; + } + +(* `Permanent *) + +type error += Invalid_activation of {pkh : Ed25519.Public_key_hash.t} + +type error += Multiple_revelation + +type error += Gas_quota_exceeded_init_deserialize (* Permanent *) + +type error += (* `Permanent *) Inconsistent_sources + +type error += + | Not_enough_endorsements_for_priority of { + required : int; + priority : int; + endorsements : int; + timestamp : Time.t; + } + +type error += (* `Permanent *) Failing_noop_error + +let () = + register_error_kind + `Temporary + ~id:"operation.wrong_endorsement_predecessor" + ~title:"Wrong endorsement predecessor" + ~description: + "Trying to include an endorsement in a block that is not the successor \ + of the endorsed one" + ~pp:(fun ppf (e, p) -> + Format.fprintf + ppf + "Wrong predecessor %a, expected %a" + Block_hash.pp + p + Block_hash.pp + e) + Data_encoding.( + obj2 + (req "expected" Block_hash.encoding) + (req "provided" Block_hash.encoding)) + (function + | Wrong_endorsement_predecessor (e, p) -> Some (e, p) | _ -> None) + (fun (e, p) -> Wrong_endorsement_predecessor (e, p)) ; + register_error_kind + `Temporary + ~id:"operation.wrong_voting_period" + ~title:"Wrong voting period" + ~description: + "Trying to include a proposal or ballot meant for another voting period" + ~pp:(fun ppf (e, p) -> + Format.fprintf ppf "Wrong voting period %ld, current is %ld" p e) + Data_encoding.( + obj2 (req "current_index" int32) (req "provided_index" int32)) + (function Wrong_voting_period (e, p) -> Some (e, p) | _ -> None) + (fun (e, p) -> Wrong_voting_period (e, p)) ; + register_error_kind + `Branch + ~id:"operation.duplicate_endorsement" + ~title:"Duplicate endorsement" + ~description:"Two endorsements received from same delegate" + ~pp:(fun ppf k -> + Format.fprintf + ppf + "Duplicate endorsement from delegate %a (possible replay attack)." + Signature.Public_key_hash.pp_short + k) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Duplicate_endorsement k -> Some k | _ -> None) + (fun k -> Duplicate_endorsement k) ; + register_error_kind + `Temporary + ~id:"operation.invalid_endorsement_level" + ~title:"Unexpected level in endorsement" + ~description: + "The level of an endorsement is inconsistent with the provided block \ + hash." + ~pp:(fun ppf () -> Format.fprintf ppf "Unexpected level in endorsement.") + Data_encoding.unit + (function Invalid_endorsement_level -> Some () | _ -> None) + (fun () -> Invalid_endorsement_level) ; + register_error_kind + `Temporary + ~id:"operation.invalid_endorsement_wrapper" + ~title:"Unexpected wrapper in endorsement" + ~description: + "The wrapper of an endorsement is inconsistent with the endorsement it \ + wraps." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The endorsement wrapper announces a block hash different from its \ + wrapped endorsement, or bears a signature.") + Data_encoding.unit + (function Invalid_endorsement_wrapper -> Some () | _ -> None) + (fun () -> Invalid_endorsement_wrapper) ; + register_error_kind + `Temporary + ~id:"operation.unwrapped_endorsement" + ~title:"Unwrapped endorsement" + ~description: + "A legacy endorsement has been applied without its required \ + slot-bearing wrapper." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "A legacy endorsement has been applied without its required \ + slot-bearing wrapper operation.") + Data_encoding.unit + (function Unwrapped_endorsement -> Some () | _ -> None) + (fun () -> Unwrapped_endorsement) ; + register_error_kind + `Permanent + ~id:"block.invalid_commitment" + ~title:"Invalid commitment in block header" + ~description:"The block header has invalid commitment." + ~pp:(fun ppf expected -> + if expected then + Format.fprintf ppf "Missing seed's nonce commitment in block header." + else + Format.fprintf + ppf + "Unexpected seed's nonce commitment in block header.") + Data_encoding.(obj1 (req "expected" bool)) + (function Invalid_commitment {expected} -> Some expected | _ -> None) + (fun expected -> Invalid_commitment {expected}) ; + register_error_kind + `Permanent + ~id:"internal_operation_replay" + ~title:"Internal operation replay" + ~description:"An internal operation was emitted twice by a script" + ~pp:(fun ppf (Internal_operation {nonce; _}) -> + Format.fprintf + ppf + "Internal operation %d was emitted twice by a script" + nonce) + Operation.internal_operation_encoding + (function Internal_operation_replay op -> Some op | _ -> None) + (fun op -> Internal_operation_replay op) ; + register_error_kind + `Permanent + ~id:"block.invalid_double_endorsement_evidence" + ~title:"Invalid double endorsement evidence" + ~description:"A double-endorsement evidence is malformed" + ~pp:(fun ppf () -> + Format.fprintf ppf "Malformed double-endorsement evidence") + Data_encoding.empty + (function Invalid_double_endorsement_evidence -> Some () | _ -> None) + (fun () -> Invalid_double_endorsement_evidence) ; + register_error_kind + `Permanent + ~id:"block.inconsistent_double_endorsement_evidence" + ~title:"Inconsistent double endorsement evidence" + ~description: + "A double-endorsement evidence is inconsistent (two distinct delegates)" + ~pp:(fun ppf (delegate1, delegate2) -> + Format.fprintf + ppf + "Inconsistent double-endorsement evidence (distinct delegate: %a and \ + %a)" + Signature.Public_key_hash.pp_short + delegate1 + Signature.Public_key_hash.pp_short + delegate2) + Data_encoding.( + obj2 + (req "delegate1" Signature.Public_key_hash.encoding) + (req "delegate2" Signature.Public_key_hash.encoding)) + (function + | Inconsistent_double_endorsement_evidence {delegate1; delegate2} -> + Some (delegate1, delegate2) + | _ -> + None) + (fun (delegate1, delegate2) -> + Inconsistent_double_endorsement_evidence {delegate1; delegate2}) ; + register_error_kind + `Branch + ~id:"block.unrequired_double_endorsement_evidence" + ~title:"Unrequired double endorsement evidence" + ~description:"A double-endorsement evidence is unrequired" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "A valid double-endorsement operation cannot be applied: the \ + associated delegate has previously been denounced in this cycle.") + Data_encoding.empty + (function Unrequired_double_endorsement_evidence -> Some () | _ -> None) + (fun () -> Unrequired_double_endorsement_evidence) ; + register_error_kind + `Temporary + ~id:"block.too_early_double_endorsement_evidence" + ~title:"Too early double endorsement evidence" + ~description:"A double-endorsement evidence is in the future" + ~pp:(fun ppf (level, current) -> + Format.fprintf + ppf + "A double-endorsement evidence is in the future (current level: %a, \ + endorsement level: %a)" + Raw_level.pp + current + Raw_level.pp + level) + Data_encoding.( + obj2 (req "level" Raw_level.encoding) (req "current" Raw_level.encoding)) + (function + | Too_early_double_endorsement_evidence {level; current} -> + Some (level, current) + | _ -> + None) + (fun (level, current) -> + Too_early_double_endorsement_evidence {level; current}) ; + register_error_kind + `Permanent + ~id:"block.outdated_double_endorsement_evidence" + ~title:"Outdated double endorsement evidence" + ~description:"A double-endorsement evidence is outdated." + ~pp:(fun ppf (level, last) -> + Format.fprintf + ppf + "A double-endorsement evidence is outdated (last acceptable level: \ + %a, endorsement level: %a)" + Raw_level.pp + last + Raw_level.pp + level) + Data_encoding.( + obj2 (req "level" Raw_level.encoding) (req "last" Raw_level.encoding)) + (function + | Outdated_double_endorsement_evidence {level; last} -> + Some (level, last) + | _ -> + None) + (fun (level, last) -> Outdated_double_endorsement_evidence {level; last}) ; + register_error_kind + `Permanent + ~id:"block.invalid_double_baking_evidence" + ~title:"Invalid double baking evidence" + ~description: + "A double-baking evidence is inconsistent (two distinct level)" + ~pp:(fun ppf (hash1, level1, hash2, level2) -> + Format.fprintf + ppf + "Invalid double-baking evidence (hash: %a and %a, levels: %ld and %ld)" + Block_hash.pp + hash1 + Block_hash.pp + hash2 + level1 + level2) + Data_encoding.( + obj4 + (req "hash1" Block_hash.encoding) + (req "level1" int32) + (req "hash2" Block_hash.encoding) + (req "level2" int32)) + (function + | Invalid_double_baking_evidence {hash1; level1; hash2; level2} -> + Some (hash1, level1, hash2, level2) + | _ -> + None) + (fun (hash1, level1, hash2, level2) -> + Invalid_double_baking_evidence {hash1; level1; hash2; level2}) ; + register_error_kind + `Permanent + ~id:"block.inconsistent_double_baking_evidence" + ~title:"Inconsistent double baking evidence" + ~description: + "A double-baking evidence is inconsistent (two distinct delegates)" + ~pp:(fun ppf (delegate1, delegate2) -> + Format.fprintf + ppf + "Inconsistent double-baking evidence (distinct delegate: %a and %a)" + Signature.Public_key_hash.pp_short + delegate1 + Signature.Public_key_hash.pp_short + delegate2) + Data_encoding.( + obj2 + (req "delegate1" Signature.Public_key_hash.encoding) + (req "delegate2" Signature.Public_key_hash.encoding)) + (function + | Inconsistent_double_baking_evidence {delegate1; delegate2} -> + Some (delegate1, delegate2) + | _ -> + None) + (fun (delegate1, delegate2) -> + Inconsistent_double_baking_evidence {delegate1; delegate2}) ; + register_error_kind + `Branch + ~id:"block.unrequired_double_baking_evidence" + ~title:"Unrequired double baking evidence" + ~description:"A double-baking evidence is unrequired" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "A valid double-baking operation cannot be applied: the associated \ + delegate has previously been denounced in this cycle.") + Data_encoding.empty + (function Unrequired_double_baking_evidence -> Some () | _ -> None) + (fun () -> Unrequired_double_baking_evidence) ; + register_error_kind + `Temporary + ~id:"block.too_early_double_baking_evidence" + ~title:"Too early double baking evidence" + ~description:"A double-baking evidence is in the future" + ~pp:(fun ppf (level, current) -> + Format.fprintf + ppf + "A double-baking evidence is in the future (current level: %a, \ + baking level: %a)" + Raw_level.pp + current + Raw_level.pp + level) + Data_encoding.( + obj2 (req "level" Raw_level.encoding) (req "current" Raw_level.encoding)) + (function + | Too_early_double_baking_evidence {level; current} -> + Some (level, current) + | _ -> + None) + (fun (level, current) -> Too_early_double_baking_evidence {level; current}) ; + register_error_kind + `Permanent + ~id:"block.outdated_double_baking_evidence" + ~title:"Outdated double baking evidence" + ~description:"A double-baking evidence is outdated." + ~pp:(fun ppf (level, last) -> + Format.fprintf + ppf + "A double-baking evidence is outdated (last acceptable level: %a, \ + baking level: %a)" + Raw_level.pp + last + Raw_level.pp + level) + Data_encoding.( + obj2 (req "level" Raw_level.encoding) (req "last" Raw_level.encoding)) + (function + | Outdated_double_baking_evidence {level; last} -> + Some (level, last) + | _ -> + None) + (fun (level, last) -> Outdated_double_baking_evidence {level; last}) ; + register_error_kind + `Permanent + ~id:"operation.invalid_activation" + ~title:"Invalid activation" + ~description: + "The given key and secret do not correspond to any existing \ + preallocated contract" + ~pp:(fun ppf pkh -> + Format.fprintf + ppf + "Invalid activation. The public key %a does not match any commitment." + Ed25519.Public_key_hash.pp + pkh) + Data_encoding.(obj1 (req "pkh" Ed25519.Public_key_hash.encoding)) + (function Invalid_activation {pkh} -> Some pkh | _ -> None) + (fun pkh -> Invalid_activation {pkh}) ; + register_error_kind + `Permanent + ~id:"block.multiple_revelation" + ~title:"Multiple revelations were included in a manager operation" + ~description: + "A manager operation should not contain more than one revelation" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Multiple revelations were included in a manager operation") + Data_encoding.empty + (function Multiple_revelation -> Some () | _ -> None) + (fun () -> Multiple_revelation) ; + register_error_kind + `Permanent + ~id:"gas_exhausted.init_deserialize" + ~title:"Not enough gas for initial deserialization of script expressions" + ~description: + "Gas limit was not high enough to deserialize the transaction \ + parameters or origination script code or initial storage, making the \ + operation impossible to parse within the provided gas bounds." + Data_encoding.empty + (function Gas_quota_exceeded_init_deserialize -> Some () | _ -> None) + (fun () -> Gas_quota_exceeded_init_deserialize) ; + register_error_kind + `Permanent + ~id:"operation.inconsistent_sources" + ~title:"Inconsistent sources in operation pack" + ~description: + "The operation pack includes operations from different sources." + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + "The operation pack includes operations from different sources.") + Data_encoding.empty + (function Inconsistent_sources -> Some () | _ -> None) + (fun () -> Inconsistent_sources) ; + register_error_kind + `Permanent + ~id:"operation.not_enough_endorsements_for_priority" + ~title:"Not enough endorsements for priority" + ~description: + "The block being validated does not include the required minimum number \ + of endorsements for this priority." + ~pp:(fun ppf (required, endorsements, priority, timestamp) -> + Format.fprintf + ppf + "Wrong number of endorsements (%i) for priority (%i), %i are expected \ + at %a" + endorsements + priority + required + Time.pp_hum + timestamp) + Data_encoding.( + obj4 + (req "required" int31) + (req "endorsements" int31) + (req "priority" int31) + (req "timestamp" Time.encoding)) + (function + | Not_enough_endorsements_for_priority + {required; endorsements; priority; timestamp} -> + Some (required, endorsements, priority, timestamp) + | _ -> + None) + (fun (required, endorsements, priority, timestamp) -> + Not_enough_endorsements_for_priority + {required; endorsements; priority; timestamp}) ; + register_error_kind + `Permanent + ~id:"operation.failing_noop" + ~title:"Failing_noop operation are not executed by the protocol" + ~description: + "The failing_noop operation is an operation that is not and never will \ + be executed by the protocol." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The failing_noop operation cannot be executed by the protocol") + Data_encoding.empty + (function Failing_noop_error -> Some () | _ -> None) + (fun () -> Failing_noop_error) + +open Apply_results + +let apply_manager_operation_content : + type kind. + Alpha_context.t -> + Script_ir_translator.unparsing_mode -> + payer:Contract.t -> + source:Contract.t -> + chain_id:Chain_id.t -> + internal:bool -> + kind manager_operation -> + ( context + * kind successful_manager_operation_result + * packed_internal_operation list ) + tzresult + Lwt.t = + fun ctxt mode ~payer ~source ~chain_id ~internal operation -> + let before_operation = + (* This context is not used for backtracking. Only to compute + gas consumption and originations for the operation result. *) + ctxt + in + Contract.must_exist ctxt source + >>=? fun () -> + Gas.consume ctxt Michelson_v1_gas.Cost_of.manager_operation + >>?= fun ctxt -> + match operation with + | Reveal _ -> + return + (* No-op: action already performed by `precheck_manager_contents`. *) + ( ctxt, + ( Reveal_result + {consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt} + : kind successful_manager_operation_result ), + [] ) + | Transaction {amount; parameters; destination; entrypoint} -> ( + Contract.spend ctxt source amount + >>=? fun ctxt -> + ( match Contract.is_implicit destination with + | None -> + return (ctxt, [], false) + | Some _ -> ( + Contract.allocated ctxt destination + >>=? function + | true -> + return (ctxt, [], false) + | false -> + Lwt.return + ( Fees.origination_burn ctxt + >|? fun (ctxt, origination_burn) -> + ( ctxt, + [ Receipt. + ( Contract payer, + Debited origination_burn, + Block_application ) ], + true ) ) ) ) + >>=? fun (ctxt, maybe_burn_balance_update, allocated_destination_contract) + -> + Contract.credit ctxt destination amount + >>=? fun ctxt -> + Contract.get_script ctxt destination + >>=? fun (ctxt, script) -> + match script with + | None -> + Lwt.return + ( ( match entrypoint with + | "default" -> + ok_unit + | entrypoint -> + error (Script_tc_errors.No_such_entrypoint entrypoint) ) + >>? (fun () -> + Script.force_decode_in_context ctxt parameters + >>? fun (arg, ctxt) -> + (* see [note] *) + (* [note]: for toplevel ops, cost is nil since the + lazy value has already been forced at precheck, so + we compute and consume the full cost again *) + let cost_arg = Script.deserialized_cost arg in + Gas.consume ctxt cost_arg + >>? fun ctxt -> + match Micheline.root arg with + | Prim (_, D_Unit, [], _) -> + (* Allow [Unit] parameter to non-scripted contracts. *) + ok ctxt + | _ -> + error + (Script_interpreter.Bad_contract_parameter destination)) + >|? fun ctxt -> + let result = + Transaction_result + { + storage = None; + lazy_storage_diff = None; + balance_updates = + Receipt.( + cleanup_balance_updates + [ (Contract source, Debited amount, Block_application); + ( Contract destination, + Credited amount, + Block_application ) ] + @ maybe_burn_balance_update); + originated_contracts = []; + consumed_gas = + Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = Z.zero; + paid_storage_size_diff = Z.zero; + allocated_destination_contract; + } + in + (ctxt, result, []) ) + | Some script -> + Script.force_decode_in_context ctxt parameters + >>?= fun (parameter, ctxt) -> + (* see [note] *) + let cost_parameter = Script.deserialized_cost parameter in + Gas.consume ctxt cost_parameter + >>?= fun ctxt -> + let step_constants = + let open Script_interpreter in + {source; payer; self = destination; amount; chain_id} + in + Script_interpreter.execute + ctxt + mode + step_constants + ~script + ~parameter + ~entrypoint + ~internal + >>=? fun {ctxt; storage; lazy_storage_diff; operations} -> + Contract.update_script_storage + ctxt + destination + storage + lazy_storage_diff + >>=? fun ctxt -> + Fees.record_paid_storage_space ctxt destination + >>=? fun (ctxt, new_size, paid_storage_size_diff, fees) -> + Contract.originated_from_current_nonce + ~since:before_operation + ~until:ctxt + >|=? fun originated_contracts -> + let result = + Transaction_result + { + storage = Some storage; + lazy_storage_diff; + balance_updates = + Receipt.cleanup_balance_updates + [ (Contract payer, Debited fees, Block_application); + (Contract source, Debited amount, Block_application); + (Contract destination, Credited amount, Block_application) + ]; + originated_contracts; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = new_size; + paid_storage_size_diff; + allocated_destination_contract; + } + in + (ctxt, result, operations) ) + | Origination {delegate; script; preorigination; credit} -> + Script.force_decode_in_context ctxt script.storage + >>?= fun (unparsed_storage, ctxt) -> + (* see [note] *) + Gas.consume ctxt (Script.deserialized_cost unparsed_storage) + >>?= fun ctxt -> + Script.force_decode_in_context ctxt script.code + >>?= fun (unparsed_code, ctxt) -> + (* see [note] *) + Gas.consume ctxt (Script.deserialized_cost unparsed_code) + >>?= fun ctxt -> + Script_ir_translator.parse_script + ctxt + ~legacy:false + ~allow_forged_in_storage:internal + script + >>=? fun (Ex_script parsed_script, ctxt) -> + Script_ir_translator.collect_lazy_storage + ctxt + parsed_script.storage_type + parsed_script.storage + >>?= fun (to_duplicate, ctxt) -> + let to_update = Script_ir_translator.no_lazy_storage_id in + Script_ir_translator.extract_lazy_storage_diff + ctxt + Optimized + parsed_script.storage_type + parsed_script.storage + ~to_duplicate + ~to_update + ~temporary:false + >>=? fun (storage, lazy_storage_diff, ctxt) -> + Script_ir_translator.unparse_data + ctxt + Optimized + parsed_script.storage_type + storage + >>=? fun (storage, ctxt) -> + let storage = Script.lazy_expr (Micheline.strip_locations storage) in + let script = {script with storage} in + Contract.spend ctxt source credit + >>=? fun ctxt -> + ( match preorigination with + | Some contract -> + assert internal ; + (* The preorigination field is only used to early return + the address of an originated contract in Michelson. + It cannot come from the outside. *) + ok (ctxt, contract) + | None -> + Contract.fresh_contract_from_current_nonce ctxt ) + >>?= fun (ctxt, contract) -> + Contract.originate + ctxt + contract + ~delegate + ~balance:credit + ~script:(script, lazy_storage_diff) + >>=? fun ctxt -> + Fees.origination_burn ctxt + >>?= fun (ctxt, origination_burn) -> + Fees.record_paid_storage_space ctxt contract + >|=? fun (ctxt, size, paid_storage_size_diff, fees) -> + let result = + Origination_result + { + lazy_storage_diff; + balance_updates = + Receipt.cleanup_balance_updates + [ (Contract payer, Debited fees, Block_application); + (Contract payer, Debited origination_burn, Block_application); + (Contract source, Debited credit, Block_application); + (Contract contract, Credited credit, Block_application) ]; + originated_contracts = [contract]; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = size; + paid_storage_size_diff; + } + in + (ctxt, result, []) + | Delegation delegate -> + Delegate.set ctxt source delegate + >|=? fun ctxt -> + ( ctxt, + Delegation_result + {consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt}, + [] ) + +type success_or_failure = Success of context | Failure + +let apply_internal_manager_operations ctxt mode ~payer ~chain_id ops = + let rec apply ctxt applied worklist = + match worklist with + | [] -> + Lwt.return (Success ctxt, List.rev applied) + | Internal_operation ({source; operation; nonce} as op) :: rest -> ( + ( if internal_nonce_already_recorded ctxt nonce then + fail (Internal_operation_replay (Internal_operation op)) + else + let ctxt = record_internal_nonce ctxt nonce in + apply_manager_operation_content + ctxt + mode + ~source + ~payer + ~chain_id + ~internal:true + operation ) + >>= function + | Error errors -> + let result = + Internal_operation_result + (op, Failed (manager_kind op.operation, errors)) + in + let skipped = + List.rev_map + (fun (Internal_operation op) -> + Internal_operation_result + (op, Skipped (manager_kind op.operation))) + rest + in + Lwt.return (Failure, List.rev (skipped @ (result :: applied))) + | Ok (ctxt, result, emitted) -> + apply + ctxt + (Internal_operation_result (op, Applied result) :: applied) + (emitted @ rest) ) + in + apply ctxt [] ops + +let precheck_manager_contents (type kind) ctxt + (op : kind Kind.manager contents) : context tzresult Lwt.t = + let (Manager_operation + {source; fee; counter; operation; gas_limit; storage_limit}) = + op + in + Gas.check_limit ctxt gas_limit + >>?= fun () -> + let ctxt = Gas.set_limit ctxt gas_limit in + Fees.check_storage_limit ctxt storage_limit + >>?= fun () -> + Contract.must_be_allocated ctxt (Contract.implicit_contract source) + >>=? fun () -> + Contract.check_counter_increment ctxt source counter + >>=? fun () -> + ( match operation with + | Reveal pk -> + Contract.reveal_manager_key ctxt source pk + | Transaction {parameters; _} -> + Lwt.return + (* Fail quickly if not enough gas for minimal deserialization cost *) + @@ record_trace Gas_quota_exceeded_init_deserialize + @@ ( Gas.check_enough ctxt (Script.minimal_deserialize_cost parameters) + >>? fun () -> + (* Fail if not enough gas for complete deserialization cost *) + Script.force_decode_in_context ctxt parameters + >|? fun (_arg, ctxt) -> ctxt ) + | Origination {script; _} -> + Lwt.return + @@ record_trace Gas_quota_exceeded_init_deserialize + @@ (* Fail quickly if not enough gas for minimal deserialization cost *) + ( Gas.( + check_enough + ctxt + ( Script.minimal_deserialize_cost script.code + +@ Script.minimal_deserialize_cost script.storage )) + >>? fun () -> + (* Fail if not enough gas for complete deserialization cost *) + Script.force_decode_in_context ctxt script.code + >>? fun (_code, ctxt) -> + Script.force_decode_in_context ctxt script.storage + >|? fun (_storage, ctxt) -> ctxt ) + | _ -> + return ctxt ) + >>=? fun ctxt -> + Contract.increment_counter ctxt source + >>=? fun ctxt -> + Contract.spend ctxt (Contract.implicit_contract source) fee + >>=? fun ctxt -> Lwt.return (add_fees ctxt fee) + +let apply_manager_contents (type kind) ctxt mode chain_id + (op : kind Kind.manager contents) : + ( success_or_failure + * kind manager_operation_result + * packed_internal_operation_result list ) + Lwt.t = + let (Manager_operation {source; operation; gas_limit; storage_limit}) = op in + (* We do not expose the internal scaling to the users. Instead, we multiply + the specified gas limit by the internal scaling. *) + let ctxt = Gas.set_limit ctxt gas_limit in + let ctxt = Fees.start_counting_storage_fees ctxt in + let source = Contract.implicit_contract source in + apply_manager_operation_content + ctxt + mode + ~source + ~payer:source + ~internal:false + ~chain_id + operation + >>= function + | Ok (ctxt, operation_results, internal_operations) -> ( + apply_internal_manager_operations + ctxt + mode + ~payer:source + ~chain_id + internal_operations + >>= function + | (Success ctxt, internal_operations_results) -> ( + Fees.burn_storage_fees ctxt ~storage_limit ~payer:source + >|= function + | Ok ctxt -> + ( Success ctxt, + Applied operation_results, + internal_operations_results ) + | Error errors -> + ( Failure, + Backtracked (operation_results, Some errors), + internal_operations_results ) ) + | (Failure, internal_operations_results) -> + Lwt.return + (Failure, Applied operation_results, internal_operations_results) ) + | Error errors -> + Lwt.return (Failure, Failed (manager_kind operation, errors), []) + +let skipped_operation_result : + type kind. kind manager_operation -> kind manager_operation_result = + function + | operation -> ( + match operation with + | Reveal _ -> + Applied + ( Reveal_result {consumed_gas = Gas.Arith.zero} + : kind successful_manager_operation_result ) + | _ -> + Skipped (manager_kind operation) ) + +let rec mark_skipped : + type kind. + baker:Signature.Public_key_hash.t -> + Level.t -> + kind Kind.manager contents_list -> + kind Kind.manager contents_result_list = + fun ~baker level -> function + | Single (Manager_operation {source; fee; operation}) -> + let source = Contract.implicit_contract source in + Single_result + (Manager_operation_result + { + balance_updates = + Receipt.cleanup_balance_updates + [ (Contract source, Debited fee, Block_application); + (Fees (baker, level.cycle), Credited fee, Block_application) + ]; + operation_result = skipped_operation_result operation; + internal_operation_results = []; + }) + | Cons (Manager_operation {source; fee; operation}, rest) -> + let source = Contract.implicit_contract source in + Cons_result + ( Manager_operation_result + { + balance_updates = + Receipt.cleanup_balance_updates + [ (Contract source, Debited fee, Block_application); + (Fees (baker, level.cycle), Credited fee, Block_application) + ]; + operation_result = skipped_operation_result operation; + internal_operation_results = []; + }, + mark_skipped ~baker level rest ) + +let rec precheck_manager_contents_list : + type kind. + Alpha_context.t -> + kind Kind.manager contents_list -> + context tzresult Lwt.t = + fun ctxt contents_list -> + match contents_list with + | Single (Manager_operation _ as op) -> + precheck_manager_contents ctxt op + | Cons ((Manager_operation _ as op), rest) -> + precheck_manager_contents ctxt op + >>=? fun ctxt -> precheck_manager_contents_list ctxt rest + +let check_manager_signature ctxt chain_id (op : _ Kind.manager contents_list) + raw_operation = + (* Currently, the [op] only contains one signature, so + all operations are required to be from the same manager. This may + change in the future, allowing several managers to group-sign a + sequence of transactions. *) + let check_same_manager (source, source_key) manager = + match manager with + | None -> + (* Consistency already checked by + [reveal_manager_key] in [precheck_manager_contents]. *) + ok (source, source_key) + | Some (manager, manager_key) -> + if Signature.Public_key_hash.equal source manager then + ok (source, Option.either manager_key source_key) + else error Inconsistent_sources + in + let rec find_source : + type kind. + kind Kind.manager contents_list -> + (Signature.public_key_hash * Signature.public_key option) option -> + (Signature.public_key_hash * Signature.public_key option) tzresult = + fun contents_list manager -> + let source (type kind) = function + | (Manager_operation {source; operation = Reveal key; _} : + kind Kind.manager contents) -> + (source, Some key) + | Manager_operation {source; _} -> + (source, None) + in + match contents_list with + | Single op -> + check_same_manager (source op) manager + | Cons (op, rest) -> + check_same_manager (source op) manager + >>? fun manager -> find_source rest (Some manager) + in + find_source op None + >>?= fun (source, source_key) -> + ( match source_key with + | Some key -> + return key + | None -> + Contract.get_manager_key ctxt source ) + >>=? fun public_key -> + Lwt.return (Operation.check_signature public_key chain_id raw_operation) + +let rec apply_manager_contents_list_rec : + type kind. + Alpha_context.t -> + Script_ir_translator.unparsing_mode -> + public_key_hash -> + Chain_id.t -> + kind Kind.manager contents_list -> + (success_or_failure * kind Kind.manager contents_result_list) Lwt.t = + fun ctxt mode baker chain_id contents_list -> + let level = Level.current ctxt in + match contents_list with + | Single (Manager_operation {source; fee; _} as op) -> + let source = Contract.implicit_contract source in + apply_manager_contents ctxt mode chain_id op + >|= fun (ctxt_result, operation_result, internal_operation_results) -> + let result = + Manager_operation_result + { + balance_updates = + Receipt.cleanup_balance_updates + [ (Contract source, Debited fee, Block_application); + (Fees (baker, level.cycle), Credited fee, Block_application) + ]; + operation_result; + internal_operation_results; + } + in + (ctxt_result, Single_result result) + | Cons ((Manager_operation {source; fee; _} as op), rest) -> ( + let source = Contract.implicit_contract source in + apply_manager_contents ctxt mode chain_id op + >>= function + | (Failure, operation_result, internal_operation_results) -> + let result = + Manager_operation_result + { + balance_updates = + Receipt.cleanup_balance_updates + [ (Contract source, Debited fee, Block_application); + ( Fees (baker, level.cycle), + Credited fee, + Block_application ) ]; + operation_result; + internal_operation_results; + } + in + Lwt.return + (Failure, Cons_result (result, mark_skipped ~baker level rest)) + | (Success ctxt, operation_result, internal_operation_results) -> + let result = + Manager_operation_result + { + balance_updates = + Receipt.cleanup_balance_updates + [ (Contract source, Debited fee, Block_application); + ( Fees (baker, level.cycle), + Credited fee, + Block_application ) ]; + operation_result; + internal_operation_results; + } + in + apply_manager_contents_list_rec ctxt mode baker chain_id rest + >|= fun (ctxt_result, results) -> + (ctxt_result, Cons_result (result, results)) ) + +let mark_backtracked results = + let rec mark_contents_list : + type kind. + kind Kind.manager contents_result_list -> + kind Kind.manager contents_result_list = function + | Single_result (Manager_operation_result op) -> + Single_result + (Manager_operation_result + { + balance_updates = op.balance_updates; + operation_result = + mark_manager_operation_result op.operation_result; + internal_operation_results = + List.map + mark_internal_operation_results + op.internal_operation_results; + }) + | Cons_result (Manager_operation_result op, rest) -> + Cons_result + ( Manager_operation_result + { + balance_updates = op.balance_updates; + operation_result = + mark_manager_operation_result op.operation_result; + internal_operation_results = + List.map + mark_internal_operation_results + op.internal_operation_results; + }, + mark_contents_list rest ) + and mark_internal_operation_results + (Internal_operation_result (kind, result)) = + Internal_operation_result (kind, mark_manager_operation_result result) + and mark_manager_operation_result : + type kind. kind manager_operation_result -> kind manager_operation_result + = function + | (Failed _ | Skipped _ | Backtracked _) as result -> + result + | Applied (Reveal_result _) as result -> + result + | Applied result -> + Backtracked (result, None) + in + mark_contents_list results + [@@coq_axiom "non-top-level mutual recursion"] + +let apply_manager_contents_list ctxt mode baker chain_id contents_list = + apply_manager_contents_list_rec ctxt mode baker chain_id contents_list + >>= fun (ctxt_result, results) -> + match ctxt_result with + | Failure -> + Lwt.return (ctxt (* backtracked *), mark_backtracked results) + | Success ctxt -> + Lazy_storage.cleanup_temporaries ctxt >|= fun ctxt -> (ctxt, results) + +let apply_contents_list (type kind) ctxt chain_id mode pred_block baker + (operation : kind operation) (contents_list : kind contents_list) : + (context * kind contents_result_list) tzresult Lwt.t = + match contents_list with + | Single + (Endorsement_with_slot + { endorsement = + { shell = {branch}; + protocol_data = {contents = Single (Endorsement {level})} } as + unslotted; + slot }) -> + if + ( match operation.protocol_data.signature with + | None -> + false + | Some _ -> + true ) + || not (Block_hash.equal operation.shell.branch branch) + then fail Invalid_endorsement_wrapper + else + let operation = unslotted (* shadow the slot box *) in + let block = operation.shell.branch in + error_unless + (Block_hash.equal block pred_block) + (Wrong_endorsement_predecessor (pred_block, block)) + >>?= fun () -> + let current_level = (Level.current ctxt).level in + error_unless + Raw_level.(succ level = current_level) + Invalid_endorsement_level + >>?= fun () -> + Baking.check_endorsement_rights ctxt chain_id operation ~slot + >>=? fun (delegate, slots, used) -> + if used then fail (Duplicate_endorsement delegate) + else + let ctxt = record_endorsement ctxt delegate in + let gap = List.length slots in + Tez.(Constants.endorsement_security_deposit ctxt *? Int64.of_int gap) + >>?= fun deposit -> + Delegate.freeze_deposit ctxt delegate deposit + >>=? fun ctxt -> + Global.get_block_priority ctxt + >>=? fun block_priority -> + Baking.endorsing_reward ctxt ~block_priority gap + >>?= fun reward -> + Delegate.freeze_rewards ctxt delegate reward + >|=? fun ctxt -> + let level = Level.from_raw ctxt level in + ( ctxt, + Single_result + (Endorsement_with_slot_result + (Endorsement_result + { + balance_updates = + Receipt.cleanup_balance_updates + [ ( Contract (Contract.implicit_contract delegate), + Debited deposit, + Block_application ); + ( Deposits (delegate, level.cycle), + Credited deposit, + Block_application ); + ( Rewards (delegate, level.cycle), + Credited reward, + Block_application ) ]; + delegate; + slots; + })) ) + | Single (Endorsement _) -> + fail Unwrapped_endorsement + | Single (Seed_nonce_revelation {level; nonce}) -> + let level = Level.from_raw ctxt level in + Nonce.reveal ctxt level nonce + >>=? fun ctxt -> + let seed_nonce_revelation_tip = + Constants.seed_nonce_revelation_tip ctxt + in + Lwt.return + ( add_rewards ctxt seed_nonce_revelation_tip + >|? fun ctxt -> + ( ctxt, + Single_result + (Seed_nonce_revelation_result + [ ( Rewards (baker, level.cycle), + Credited seed_nonce_revelation_tip, + Block_application ) ]) ) ) + | Single (Double_endorsement_evidence {op1; op2; slot}) -> ( + match (op1.protocol_data.contents, op2.protocol_data.contents) with + | (Single (Endorsement e1), Single (Endorsement e2)) + when Raw_level.(e1.level = e2.level) + && not (Block_hash.equal op1.shell.branch op2.shell.branch) -> + let level = Level.from_raw ctxt e1.level in + let oldest_level = Level.last_allowed_fork_level ctxt in + fail_unless + Level.(level < Level.current ctxt) + (Too_early_double_endorsement_evidence + {level = level.level; current = (Level.current ctxt).level}) + >>=? fun () -> + fail_unless + Raw_level.(oldest_level <= level.level) + (Outdated_double_endorsement_evidence + {level = level.level; last = oldest_level}) + >>=? fun () -> + Baking.check_endorsement_rights ctxt chain_id op1 ~slot + >>=? fun (delegate1, _, _) -> + Baking.check_endorsement_rights ctxt chain_id op2 ~slot + >>=? fun (delegate2, _, _) -> + fail_unless + (Signature.Public_key_hash.equal delegate1 delegate2) + (Inconsistent_double_endorsement_evidence {delegate1; delegate2}) + >>=? fun () -> + Delegate.has_frozen_balance ctxt delegate1 level.cycle + >>=? fun valid -> + fail_unless valid Unrequired_double_endorsement_evidence + >>=? fun () -> + Delegate.punish ctxt delegate1 level.cycle + >>=? fun (ctxt, balance) -> + Lwt.return Tez.(balance.deposit +? balance.fees) + >>=? fun burned -> + let reward = + match Tez.(burned /? 2L) with Ok v -> v | Error _ -> Tez.zero + in + add_rewards ctxt reward + >>?= fun ctxt -> + let current_cycle = (Level.current ctxt).cycle in + return + ( ctxt, + Single_result + (Double_endorsement_evidence_result + (Receipt.cleanup_balance_updates + [ ( Deposits (delegate1, level.cycle), + Debited balance.deposit, + Block_application ); + ( Fees (delegate1, level.cycle), + Debited balance.fees, + Block_application ); + ( Rewards (delegate1, level.cycle), + Debited balance.rewards, + Block_application ); + ( Rewards (baker, current_cycle), + Credited reward, + Block_application ) ])) ) + | (_, _) -> + fail Invalid_double_endorsement_evidence ) + | Single (Double_baking_evidence {bh1; bh2}) -> + let hash1 = Block_header.hash bh1 in + let hash2 = Block_header.hash bh2 in + fail_unless + ( Compare.Int32.(bh1.shell.level = bh2.shell.level) + && not (Block_hash.equal hash1 hash2) ) + (Invalid_double_baking_evidence + {hash1; level1 = bh1.shell.level; hash2; level2 = bh2.shell.level}) + >>=? fun () -> + Lwt.return (Raw_level.of_int32 bh1.shell.level) + >>=? fun raw_level -> + let oldest_level = Level.last_allowed_fork_level ctxt in + fail_unless + Raw_level.(raw_level < (Level.current ctxt).level) + (Too_early_double_baking_evidence + {level = raw_level; current = (Level.current ctxt).level}) + >>=? fun () -> + fail_unless + Raw_level.(oldest_level <= raw_level) + (Outdated_double_baking_evidence + {level = raw_level; last = oldest_level}) + >>=? fun () -> + let level = Level.from_raw ctxt raw_level in + Roll.baking_rights_owner + ctxt + level + ~priority:bh1.protocol_data.contents.priority + >>=? fun delegate1 -> + Baking.check_signature bh1 chain_id delegate1 + >>=? fun () -> + Roll.baking_rights_owner + ctxt + level + ~priority:bh2.protocol_data.contents.priority + >>=? fun delegate2 -> + Baking.check_signature bh2 chain_id delegate2 + >>=? fun () -> + fail_unless + (Signature.Public_key.equal delegate1 delegate2) + (Inconsistent_double_baking_evidence + { + delegate1 = Signature.Public_key.hash delegate1; + delegate2 = Signature.Public_key.hash delegate2; + }) + >>=? fun () -> + let delegate = Signature.Public_key.hash delegate1 in + Delegate.has_frozen_balance ctxt delegate level.cycle + >>=? fun valid -> + fail_unless valid Unrequired_double_baking_evidence + >>=? fun () -> + Delegate.punish ctxt delegate level.cycle + >>=? fun (ctxt, balance) -> + Tez.(balance.deposit +? balance.fees) + >>?= fun burned -> + let reward = + match Tez.(burned /? 2L) with Ok v -> v | Error _ -> Tez.zero + in + Lwt.return + ( add_rewards ctxt reward + >|? fun ctxt -> + let current_cycle = (Level.current ctxt).cycle in + ( ctxt, + Single_result + (Double_baking_evidence_result + (Receipt.cleanup_balance_updates + [ ( Deposits (delegate, level.cycle), + Debited balance.deposit, + Block_application ); + ( Fees (delegate, level.cycle), + Debited balance.fees, + Block_application ); + ( Rewards (delegate, level.cycle), + Debited balance.rewards, + Block_application ); + ( Rewards (baker, current_cycle), + Credited reward, + Block_application ) ])) ) ) + | Single (Activate_account {id = pkh; activation_code}) -> ( + let blinded_pkh = + Blinded_public_key_hash.of_ed25519_pkh activation_code pkh + in + Commitment.find ctxt blinded_pkh + >>=? function + | None -> + fail (Invalid_activation {pkh}) + | Some amount -> + Commitment.remove_existing ctxt blinded_pkh + >>=? fun ctxt -> + let contract = Contract.implicit_contract (Signature.Ed25519 pkh) in + Contract.(credit ctxt contract amount) + >|=? fun ctxt -> + ( ctxt, + Single_result + (Activate_account_result + [(Contract contract, Credited amount, Block_application)]) ) ) + | Single (Proposals {source; period; proposals}) -> + Roll.delegate_pubkey ctxt source + >>=? fun delegate -> + Operation.check_signature delegate chain_id operation + >>?= fun () -> + Voting_period.get_current ctxt + >>=? fun {index = current_period; _} -> + error_unless + Compare.Int32.(current_period = period) + (Wrong_voting_period (current_period, period)) + >>?= fun () -> + Amendment.record_proposals ctxt source proposals + >|=? fun ctxt -> (ctxt, Single_result Proposals_result) + | Single (Ballot {source; period; proposal; ballot}) -> + Roll.delegate_pubkey ctxt source + >>=? fun delegate -> + Operation.check_signature delegate chain_id operation + >>?= fun () -> + Voting_period.get_current ctxt + >>=? fun {index = current_period; _} -> + error_unless + Compare.Int32.(current_period = period) + (Wrong_voting_period (current_period, period)) + >>?= fun () -> + Amendment.record_ballot ctxt source proposal ballot + >|=? fun ctxt -> (ctxt, Single_result Ballot_result) + | Single (Failing_noop _) -> + (* Failing_noop _ always fails *) + fail Failing_noop_error + | Single (Manager_operation _) as op -> + precheck_manager_contents_list ctxt op + >>=? fun ctxt -> + check_manager_signature ctxt chain_id op operation + >>=? fun () -> + apply_manager_contents_list ctxt mode baker chain_id op >|= ok + | Cons (Manager_operation _, _) as op -> + precheck_manager_contents_list ctxt op + >>=? fun ctxt -> + check_manager_signature ctxt chain_id op operation + >>=? fun () -> + apply_manager_contents_list ctxt mode baker chain_id op >|= ok + +let apply_operation ctxt chain_id mode pred_block baker hash operation = + let ctxt = Contract.init_origination_nonce ctxt hash in + apply_contents_list + ctxt + chain_id + mode + pred_block + baker + operation + operation.protocol_data.contents + >|=? fun (ctxt, result) -> + let ctxt = Gas.set_unlimited ctxt in + let ctxt = Contract.unset_origination_nonce ctxt in + (ctxt, {contents = result}) + +let may_snapshot_roll ctxt = + let level = Alpha_context.Level.current ctxt in + let blocks_per_roll_snapshot = Constants.blocks_per_roll_snapshot ctxt in + if + Compare.Int32.equal + (Int32.rem level.cycle_position blocks_per_roll_snapshot) + (Int32.pred blocks_per_roll_snapshot) + then Alpha_context.Roll.snapshot_rolls ctxt + else return ctxt + +let may_start_new_cycle ctxt = + match Baking.dawn_of_a_new_cycle ctxt with + | None -> + return (ctxt, [], []) + | Some last_cycle -> + Seed.cycle_end ctxt last_cycle + >>=? fun (ctxt, unrevealed) -> + Roll.cycle_end ctxt last_cycle + >>=? fun ctxt -> + Delegate.cycle_end ctxt last_cycle unrevealed + >>=? fun (ctxt, update_balances, deactivated) -> + Bootstrap.cycle_end ctxt last_cycle + >|=? fun ctxt -> (ctxt, update_balances, deactivated) + +let endorsement_rights_of_pred_level ctxt = + match Level.pred ctxt (Level.current ctxt) with + | None -> + assert false (* genesis *) + | Some pred_level -> + Baking.endorsement_rights ctxt pred_level + +let begin_full_construction ctxt pred_timestamp protocol_data = + Alpha_context.Global.set_block_priority + ctxt + protocol_data.Block_header.priority + >>=? fun ctxt -> + Baking.check_baking_rights ctxt protocol_data pred_timestamp + >>=? fun (delegate_pk, block_delay) -> + let ctxt = Fitness.increase ctxt in + endorsement_rights_of_pred_level ctxt + >|=? fun rights -> + let ctxt = init_endorsements ctxt rights in + (ctxt, protocol_data, delegate_pk, block_delay) + +let begin_partial_construction ctxt = + let ctxt = Fitness.increase ctxt in + endorsement_rights_of_pred_level ctxt + >|=? fun rights -> init_endorsements ctxt rights + +let begin_application ctxt chain_id block_header pred_timestamp = + Alpha_context.Global.set_block_priority + ctxt + block_header.Block_header.protocol_data.contents.priority + >>=? fun ctxt -> + let current_level = Alpha_context.Level.current ctxt in + Baking.check_proof_of_work_stamp ctxt block_header + >>?= fun () -> + Baking.check_fitness_gap ctxt block_header + >>?= fun () -> + Baking.check_baking_rights + ctxt + block_header.protocol_data.contents + pred_timestamp + >>=? fun (delegate_pk, block_delay) -> + Baking.check_signature block_header chain_id delegate_pk + >>=? fun () -> + let has_commitment = + Option.is_some block_header.protocol_data.contents.seed_nonce_hash + in + error_unless + Compare.Bool.(has_commitment = current_level.expected_commitment) + (Invalid_commitment {expected = current_level.expected_commitment}) + >>?= fun () -> + let ctxt = Fitness.increase ctxt in + endorsement_rights_of_pred_level ctxt + >|=? fun rights -> + let ctxt = init_endorsements ctxt rights in + (ctxt, delegate_pk, block_delay) + +let check_minimum_endorsements ctxt protocol_data block_delay + included_endorsements = + let minimum = Baking.minimum_allowed_endorsements ctxt ~block_delay in + let timestamp = Timestamp.current ctxt in + error_unless + Compare.Int.(included_endorsements >= minimum) + (Not_enough_endorsements_for_priority + { + required = minimum; + priority = protocol_data.Block_header.priority; + endorsements = included_endorsements; + timestamp; + }) + +let finalize_application ctxt protocol_data delegate ~block_delay + migration_balance_updates = + let included_endorsements = included_endorsements ctxt in + check_minimum_endorsements + ctxt + protocol_data + block_delay + included_endorsements + >>?= fun () -> + let deposit = Constants.block_security_deposit ctxt in + add_deposit ctxt delegate deposit + >>?= fun ctxt -> + Baking.baking_reward + ctxt + ~block_priority:protocol_data.priority + ~included_endorsements + >>?= fun reward -> + add_rewards ctxt reward + >>?= fun ctxt -> + Signature.Public_key_hash.Map.fold + (fun delegate deposit ctxt -> + ctxt >>=? fun ctxt -> Delegate.freeze_deposit ctxt delegate deposit) + (get_deposits ctxt) + (return ctxt) + >>=? fun ctxt -> + (* end of level (from this point nothing should fail) *) + let fees = Alpha_context.get_fees ctxt in + Delegate.freeze_fees ctxt delegate fees + >>=? fun ctxt -> + let rewards = Alpha_context.get_rewards ctxt in + Delegate.freeze_rewards ctxt delegate rewards + >>=? fun ctxt -> + ( match protocol_data.Block_header.seed_nonce_hash with + | None -> + return ctxt + | Some nonce_hash -> + Nonce.record_hash ctxt {nonce_hash; delegate; rewards; fees} ) + >>=? fun ctxt -> + (* end of cycle *) + may_snapshot_roll ctxt + >>=? fun ctxt -> + may_start_new_cycle ctxt + >>=? fun (ctxt, balance_updates, deactivated) -> + Amendment.may_start_new_voting_period ctxt + >>=? fun ctxt -> + let cycle = (Level.current ctxt).cycle in + let balance_updates = + Receipt.( + cleanup_balance_updates + ( migration_balance_updates + @ [ ( Contract (Contract.implicit_contract delegate), + Debited deposit, + Block_application ); + (Deposits (delegate, cycle), Credited deposit, Block_application); + (Rewards (delegate, cycle), Credited reward, Block_application) ] + @ balance_updates )) + in + let consumed_gas = + Gas.Arith.sub + (Gas.Arith.fp @@ Constants.hard_gas_limit_per_block ctxt) + (Alpha_context.Gas.block_level ctxt) + in + (* This value is different than the new [voting_period_info] below for + compatibility reasons, the field [voting_period_kind] is deprecated and will + be removed in a future version. *) + Alpha_context.Voting_period.get_current_info ctxt + >>=? fun {voting_period = {kind; _}; _} -> + Alpha_context.Voting_period.get_rpc_fixed_current_info ctxt + >|=? fun ({voting_period; position; _} as voting_period_info) -> + let level_info = Alpha_context.Level.current ctxt in + let receipt = + Apply_results. + { + baker = delegate; + level = + Level.to_deprecated_type + level_info + ~voting_period_index:voting_period.index + ~voting_period_position:position; + level_info; + voting_period_info; + voting_period_kind = kind; + nonce_hash = protocol_data.seed_nonce_hash; + consumed_gas; + deactivated; + balance_updates; + } + in + (ctxt, receipt) diff --git a/src/proto_009_PsFLoren/lib_protocol/apply.mli b/src/proto_009_PsFLoren/lib_protocol/apply.mli new file mode 100644 index 0000000000000000000000000000000000000000..fbac491292c283bda50c67e81852496ff6794237 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/apply.mli @@ -0,0 +1,156 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Apply_results + +type error += Wrong_endorsement_predecessor of Block_hash.t * Block_hash.t + +type error += Duplicate_endorsement of Signature.Public_key_hash.t + +type error += Invalid_endorsement_level + +type error += Unwrapped_endorsement + +type error += Invalid_commitment of {expected : bool} + +type error += Internal_operation_replay of packed_internal_operation + +type error += Invalid_double_endorsement_evidence + +type error += + | Inconsistent_double_endorsement_evidence of { + delegate1 : Signature.Public_key_hash.t; + delegate2 : Signature.Public_key_hash.t; + } + +type error += + | Too_early_double_endorsement_evidence of { + level : Raw_level.t; + current : Raw_level.t; + } + +type error += + | Outdated_double_endorsement_evidence of { + level : Raw_level.t; + last : Raw_level.t; + } + +type error += + | Invalid_double_baking_evidence of { + hash1 : Block_hash.t; + level1 : Int32.t; + hash2 : Block_hash.t; + level2 : Int32.t; + } + +type error += + | Inconsistent_double_baking_evidence of { + delegate1 : Signature.Public_key_hash.t; + delegate2 : Signature.Public_key_hash.t; + } + +type error += + | Too_early_double_baking_evidence of { + level : Raw_level.t; + current : Raw_level.t; + } + +type error += + | Outdated_double_baking_evidence of { + level : Raw_level.t; + last : Raw_level.t; + } + +type error += Invalid_activation of {pkh : Ed25519.Public_key_hash.t} + +type error += Gas_quota_exceeded_init_deserialize + +type error += Inconsistent_sources + +type error += + | Not_enough_endorsements_for_priority of { + required : int; + priority : int; + endorsements : int; + timestamp : Time.t; + } + +type error += (* `Permanent *) Failing_noop_error + +val begin_partial_construction : t -> (t, error trace) result Lwt.t + +val begin_full_construction : + t -> + Time.t -> + Block_header.contents -> + (t * Block_header.contents * public_key * Period.t, error trace) result Lwt.t + +val begin_application : + t -> + Chain_id.t -> + Block_header.t -> + Time.t -> + (t * public_key * Period.t, error trace) result Lwt.t + +val apply_operation : + t -> + Chain_id.t -> + Script_ir_translator.unparsing_mode -> + Block_hash.t -> + public_key_hash -> + Operation_list_hash.elt -> + 'a operation -> + (t * 'a operation_metadata, error trace) result Lwt.t + +val finalize_application : + t -> + Block_header.contents -> + public_key_hash -> + block_delay:Period.t -> + Receipt.balance_updates -> + (t * block_metadata, error trace) result Lwt.t + +val apply_manager_contents_list : + t -> + Script_ir_translator.unparsing_mode -> + public_key_hash -> + Chain_id.t -> + 'a Kind.manager contents_list -> + (t * 'a Kind.manager contents_result_list) Lwt.t + +val apply_contents_list : + t -> + Chain_id.t -> + Script_ir_translator.unparsing_mode -> + Block_hash.t -> + public_key_hash -> + 'kind operation -> + 'kind contents_list -> + (t * 'kind contents_result_list) tzresult Lwt.t + +val check_minimum_endorsements : + t -> Block_header.contents -> Period.t -> int -> (unit, error trace) result diff --git a/src/proto_009_PsFLoren/lib_protocol/apply_results.ml b/src/proto_009_PsFLoren/lib_protocol/apply_results.ml new file mode 100644 index 0000000000000000000000000000000000000000..9c12f50d3a545e52f358f2c1c549a67ba010d52e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/apply_results.ml @@ -0,0 +1,1300 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Data_encoding + +let error_encoding = + def + "error" + ~description: + "The full list of RPC errors would be too long to include.\n\ + It is available at RPC `/errors` (GET).\n\ + Errors specific to protocol Alpha have an id that starts with \ + `proto.alpha`." + @@ splitted + ~json: + (conv + (fun err -> + Data_encoding.Json.construct Error_monad.error_encoding err) + (fun json -> + Data_encoding.Json.destruct Error_monad.error_encoding json) + json) + ~binary:Error_monad.error_encoding + +let trace_encoding = make_trace_encoding error_encoding + +type _ successful_manager_operation_result = + | Reveal_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.reveal successful_manager_operation_result + | Transaction_result : { + storage : Script.expr option; + lazy_storage_diff : Lazy_storage.diffs option; + balance_updates : Receipt.balance_updates; + originated_contracts : Contract.t list; + consumed_gas : Gas.Arith.fp; + storage_size : Z.t; + paid_storage_size_diff : Z.t; + allocated_destination_contract : bool; + } + -> Kind.transaction successful_manager_operation_result + | Origination_result : { + lazy_storage_diff : Lazy_storage.diffs option; + balance_updates : Receipt.balance_updates; + originated_contracts : Contract.t list; + consumed_gas : Gas.Arith.fp; + storage_size : Z.t; + paid_storage_size_diff : Z.t; + } + -> Kind.origination successful_manager_operation_result + | Delegation_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.delegation successful_manager_operation_result + +type packed_successful_manager_operation_result = + | Successful_manager_result : + 'kind successful_manager_operation_result + -> packed_successful_manager_operation_result + +type 'kind manager_operation_result = + | Applied of 'kind successful_manager_operation_result + | Backtracked of + 'kind successful_manager_operation_result * error trace option + | Failed : 'kind Kind.manager * error trace -> 'kind manager_operation_result + | Skipped : 'kind Kind.manager -> 'kind manager_operation_result + +type packed_internal_operation_result = + | Internal_operation_result : + 'kind internal_operation * 'kind manager_operation_result + -> packed_internal_operation_result + +module Manager_result = struct + type 'kind case = + | MCase : { + op_case : 'kind Operation.Encoding.Manager_operations.case; + encoding : 'a Data_encoding.t; + kind : 'kind Kind.manager; + iselect : + packed_internal_operation_result -> + ('kind internal_operation * 'kind manager_operation_result) option; + select : + packed_successful_manager_operation_result -> + 'kind successful_manager_operation_result option; + proj : 'kind successful_manager_operation_result -> 'a; + inj : 'a -> 'kind successful_manager_operation_result; + t : 'kind manager_operation_result Data_encoding.t; + } + -> 'kind case + + let make ~op_case ~encoding ~kind ~iselect ~select ~proj ~inj = + let (Operation.Encoding.Manager_operations.MCase {name; _}) = op_case in + let t = + def (Format.asprintf "operation.alpha.operation_result.%s" name) + @@ union + ~tag_size:`Uint8 + [ case + (Tag 0) + ~title:"Applied" + (merge_objs (obj1 (req "status" (constant "applied"))) encoding) + (fun o -> + match o with + | Skipped _ | Failed _ | Backtracked _ -> + None + | Applied o -> ( + match select (Successful_manager_result o) with + | None -> + None + | Some o -> + Some ((), proj o) )) + (fun ((), x) -> Applied (inj x)); + case + (Tag 1) + ~title:"Failed" + (obj2 + (req "status" (constant "failed")) + (req "errors" trace_encoding)) + (function Failed (_, errs) -> Some ((), errs) | _ -> None) + (fun ((), errs) -> Failed (kind, errs)); + case + (Tag 2) + ~title:"Skipped" + (obj1 (req "status" (constant "skipped"))) + (function Skipped _ -> Some () | _ -> None) + (fun () -> Skipped kind); + case + (Tag 3) + ~title:"Backtracked" + (merge_objs + (obj2 + (req "status" (constant "backtracked")) + (opt "errors" trace_encoding)) + encoding) + (fun o -> + match o with + | Skipped _ | Failed _ | Applied _ -> + None + | Backtracked (o, errs) -> ( + match select (Successful_manager_result o) with + | None -> + None + | Some o -> + Some (((), errs), proj o) )) + (fun (((), errs), x) -> Backtracked (inj x, errs)) ] + in + MCase {op_case; encoding; kind; iselect; select; proj; inj; t} + + let reveal_case = + make + ~op_case:Operation.Encoding.Manager_operations.reveal_case + ~encoding: + Data_encoding.( + obj2 + (dft "consumed_gas" Gas.Arith.n_integral_encoding Gas.Arith.zero) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~iselect:(function + | Internal_operation_result (({operation = Reveal _; _} as op), res) -> + Some (op, res) + | _ -> + None) + ~select:(function + | Successful_manager_result (Reveal_result _ as op) -> + Some op + | _ -> + None) + ~kind:Kind.Reveal_manager_kind + ~proj:(function + | Reveal_result {consumed_gas} -> + (Gas.Arith.ceil consumed_gas, consumed_gas)) + ~inj:(fun (consumed_gas, consumed_milligas) -> + assert (Gas.Arith.(equal (ceil consumed_milligas) consumed_gas)) ; + Reveal_result {consumed_gas = consumed_milligas}) + + let transaction_case = + make + ~op_case:Operation.Encoding.Manager_operations.transaction_case + ~encoding: + (obj10 + (opt "storage" Script.expr_encoding) + (opt + (* The field [big_map_diff] is deprecated since 008, use [lazy_storage_diff] instead. + Is it kept here for a transition period, for tool like indexers to update. + TODO(009): remove it. *) + "big_map_diff" + Lazy_storage.legacy_big_map_diff_encoding) + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "originated_contracts" (list Contract.encoding) []) + (dft "consumed_gas" Gas.Arith.n_integral_encoding Gas.Arith.zero) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "storage_size" z Z.zero) + (dft "paid_storage_size_diff" z Z.zero) + (dft "allocated_destination_contract" bool false) + (opt "lazy_storage_diff" Lazy_storage.encoding)) + ~iselect:(function + | Internal_operation_result + (({operation = Transaction _; _} as op), res) -> + Some (op, res) + | _ -> + None) + ~select:(function + | Successful_manager_result (Transaction_result _ as op) -> + Some op + | _ -> + None) + ~kind:Kind.Transaction_manager_kind + ~proj:(function + | Transaction_result + { storage; + lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + allocated_destination_contract } -> + ( storage, + lazy_storage_diff, + balance_updates, + originated_contracts, + Gas.Arith.ceil consumed_gas, + consumed_gas, + storage_size, + paid_storage_size_diff, + allocated_destination_contract, + lazy_storage_diff )) + ~inj: + (fun ( storage, + legacy_lazy_storage_diff, + balance_updates, + originated_contracts, + consumed_gas, + consumed_milligas, + storage_size, + paid_storage_size_diff, + allocated_destination_contract, + lazy_storage_diff ) -> + assert (Gas.Arith.(equal (ceil consumed_milligas) consumed_gas)) ; + let lazy_storage_diff = + Option.either lazy_storage_diff legacy_lazy_storage_diff + in + Transaction_result + { + storage; + lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas = consumed_milligas; + storage_size; + paid_storage_size_diff; + allocated_destination_contract; + }) + + let origination_case = + make + ~op_case:Operation.Encoding.Manager_operations.origination_case + ~encoding: + (obj8 + (opt + (* The field [big_map_diff] is deprecated since 008, use [lazy_storage_diff] instead. + Is it kept here for a transition period, for tool like indexers to update. + TODO(009): remove it. *) + "big_map_diff" + Lazy_storage.legacy_big_map_diff_encoding) + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "originated_contracts" (list Contract.encoding) []) + (dft "consumed_gas" Gas.Arith.n_integral_encoding Gas.Arith.zero) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "storage_size" z Z.zero) + (dft "paid_storage_size_diff" z Z.zero) + (opt "lazy_storage_diff" Lazy_storage.encoding)) + ~iselect:(function + | Internal_operation_result + (({operation = Origination _; _} as op), res) -> + Some (op, res) + | _ -> + None) + ~select:(function + | Successful_manager_result (Origination_result _ as op) -> + Some op + | _ -> + None) + ~proj:(function + | Origination_result + { lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff } -> + ( lazy_storage_diff, + balance_updates, + originated_contracts, + Gas.Arith.ceil consumed_gas, + consumed_gas, + storage_size, + paid_storage_size_diff, + lazy_storage_diff )) + ~kind:Kind.Origination_manager_kind + ~inj: + (fun ( legacy_lazy_storage_diff, + balance_updates, + originated_contracts, + consumed_gas, + consumed_milligas, + storage_size, + paid_storage_size_diff, + lazy_storage_diff ) -> + assert (Gas.Arith.(equal (ceil consumed_milligas) consumed_gas)) ; + let lazy_storage_diff = + Option.either lazy_storage_diff legacy_lazy_storage_diff + in + Origination_result + { + lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas = consumed_milligas; + storage_size; + paid_storage_size_diff; + }) + + let delegation_case = + make + ~op_case:Operation.Encoding.Manager_operations.delegation_case + ~encoding: + Data_encoding.( + obj2 + (dft "consumed_gas" Gas.Arith.n_integral_encoding Gas.Arith.zero) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~iselect:(function + | Internal_operation_result (({operation = Delegation _; _} as op), res) + -> + Some (op, res) + | _ -> + None) + ~select:(function + | Successful_manager_result (Delegation_result _ as op) -> + Some op + | _ -> + None) + ~kind:Kind.Delegation_manager_kind + ~proj:(function + | Delegation_result {consumed_gas} -> + (Gas.Arith.ceil consumed_gas, consumed_gas)) + ~inj:(fun (consumed_gas, consumed_milligas) -> + assert (Gas.Arith.(equal (ceil consumed_milligas) consumed_gas)) ; + Delegation_result {consumed_gas = consumed_milligas}) +end + +let internal_operation_result_encoding : + packed_internal_operation_result Data_encoding.t = + let make (type kind) + (Manager_result.MCase res_case : kind Manager_result.case) = + let (Operation.Encoding.Manager_operations.MCase op_case) = + res_case.op_case + in + case + (Tag op_case.tag) + ~title:op_case.name + (merge_objs + (obj3 + (req "kind" (constant op_case.name)) + (req "source" Contract.encoding) + (req "nonce" uint16)) + (merge_objs op_case.encoding (obj1 (req "result" res_case.t)))) + (fun op -> + match res_case.iselect op with + | Some (op, res) -> + Some (((), op.source, op.nonce), (op_case.proj op.operation, res)) + | None -> + None) + (fun (((), source, nonce), (op, res)) -> + let op = {source; operation = op_case.inj op; nonce} in + Internal_operation_result (op, res)) + in + def "operation.alpha.internal_operation_result" + @@ union + [ make Manager_result.reveal_case; + make Manager_result.transaction_case; + make Manager_result.origination_case; + make Manager_result.delegation_case ] + +type 'kind contents_result = + | Endorsement_result : { + balance_updates : Receipt.balance_updates; + delegate : Signature.Public_key_hash.t; + slots : int list; + } + -> Kind.endorsement contents_result + | Seed_nonce_revelation_result : + Receipt.balance_updates + -> Kind.seed_nonce_revelation contents_result + | Endorsement_with_slot_result : + Kind.endorsement contents_result + -> Kind.endorsement_with_slot contents_result + | Double_endorsement_evidence_result : + Receipt.balance_updates + -> Kind.double_endorsement_evidence contents_result + | Double_baking_evidence_result : + Receipt.balance_updates + -> Kind.double_baking_evidence contents_result + | Activate_account_result : + Receipt.balance_updates + -> Kind.activate_account contents_result + | Proposals_result : Kind.proposals contents_result + | Ballot_result : Kind.ballot contents_result + | Manager_operation_result : { + balance_updates : Receipt.balance_updates; + operation_result : 'kind manager_operation_result; + internal_operation_results : packed_internal_operation_result list; + } + -> 'kind Kind.manager contents_result + +type packed_contents_result = + | Contents_result : 'kind contents_result -> packed_contents_result + +type packed_contents_and_result = + | Contents_and_result : + 'kind Operation.contents * 'kind contents_result + -> packed_contents_and_result + +type ('a, 'b) eq = Eq : ('a, 'a) eq + +let equal_manager_kind : + type a b. a Kind.manager -> b Kind.manager -> (a, b) eq option = + fun ka kb -> + match (ka, kb) with + | (Kind.Reveal_manager_kind, Kind.Reveal_manager_kind) -> + Some Eq + | (Kind.Reveal_manager_kind, _) -> + None + | (Kind.Transaction_manager_kind, Kind.Transaction_manager_kind) -> + Some Eq + | (Kind.Transaction_manager_kind, _) -> + None + | (Kind.Origination_manager_kind, Kind.Origination_manager_kind) -> + Some Eq + | (Kind.Origination_manager_kind, _) -> + None + | (Kind.Delegation_manager_kind, Kind.Delegation_manager_kind) -> + Some Eq + | (Kind.Delegation_manager_kind, _) -> + None + +module Encoding = struct + type 'kind case = + | Case : { + op_case : 'kind Operation.Encoding.case; + encoding : 'a Data_encoding.t; + select : packed_contents_result -> 'kind contents_result option; + mselect : + packed_contents_and_result -> + ('kind contents * 'kind contents_result) option; + proj : 'kind contents_result -> 'a; + inj : 'a -> 'kind contents_result; + } + -> 'kind case + + let tagged_case tag name args proj inj = + let open Data_encoding in + case + tag + ~title:(String.capitalize_ascii name) + (merge_objs (obj1 (req "kind" (constant name))) args) + (fun x -> match proj x with None -> None | Some x -> Some ((), x)) + (fun ((), x) -> inj x) + + let endorsement_case = + Case + { + op_case = Operation.Encoding.endorsement_case; + encoding = + obj3 + (req "balance_updates" Receipt.balance_updates_encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "slots" (list uint16)); + select = + (function + | Contents_result (Endorsement_result _ as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result ((Endorsement _ as op), res) -> + Some (op, res) + | _ -> + None); + proj = + (function + | Endorsement_result {balance_updates; delegate; slots} -> + (balance_updates, delegate, slots)); + inj = + (fun (balance_updates, delegate, slots) -> + Endorsement_result {balance_updates; delegate; slots}); + } + + let seed_nonce_revelation_case = + Case + { + op_case = Operation.Encoding.seed_nonce_revelation_case; + encoding = + obj1 (req "balance_updates" Receipt.balance_updates_encoding); + select = + (function + | Contents_result (Seed_nonce_revelation_result _ as op) -> + Some op + | _ -> + None); + mselect = + (function + | Contents_and_result ((Seed_nonce_revelation _ as op), res) -> + Some (op, res) + | _ -> + None); + proj = (fun (Seed_nonce_revelation_result bus) -> bus); + inj = (fun bus -> Seed_nonce_revelation_result bus); + } + + let endorsement_with_slot_case = + Case + { + op_case = Operation.Encoding.endorsement_with_slot_case; + encoding = + obj3 + (req "balance_updates" Receipt.balance_updates_encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "slots" (list uint16)); + select = + (function + | Contents_result (Endorsement_with_slot_result _ as op) -> + Some op + | _ -> + None); + mselect = + (function + | Contents_and_result ((Endorsement_with_slot _ as op), res) -> + Some (op, res) + | _ -> + None); + proj = + (function + | Endorsement_with_slot_result + (Endorsement_result {balance_updates; delegate; slots}) -> + (balance_updates, delegate, slots)); + inj = + (fun (balance_updates, delegate, slots) -> + Endorsement_with_slot_result + (Endorsement_result {balance_updates; delegate; slots})); + } + + let double_endorsement_evidence_case = + Case + { + op_case = Operation.Encoding.double_endorsement_evidence_case; + encoding = + obj1 (req "balance_updates" Receipt.balance_updates_encoding); + select = + (function + | Contents_result (Double_endorsement_evidence_result _ as op) -> + Some op + | _ -> + None); + mselect = + (function + | Contents_and_result ((Double_endorsement_evidence _ as op), res) -> + Some (op, res) + | _ -> + None); + proj = (fun (Double_endorsement_evidence_result bus) -> bus); + inj = (fun bus -> Double_endorsement_evidence_result bus); + } + + let double_baking_evidence_case = + Case + { + op_case = Operation.Encoding.double_baking_evidence_case; + encoding = + obj1 (req "balance_updates" Receipt.balance_updates_encoding); + select = + (function + | Contents_result (Double_baking_evidence_result _ as op) -> + Some op + | _ -> + None); + mselect = + (function + | Contents_and_result ((Double_baking_evidence _ as op), res) -> + Some (op, res) + | _ -> + None); + proj = (fun (Double_baking_evidence_result bus) -> bus); + inj = (fun bus -> Double_baking_evidence_result bus); + } + + let activate_account_case = + Case + { + op_case = Operation.Encoding.activate_account_case; + encoding = + obj1 (req "balance_updates" Receipt.balance_updates_encoding); + select = + (function + | Contents_result (Activate_account_result _ as op) -> + Some op + | _ -> + None); + mselect = + (function + | Contents_and_result ((Activate_account _ as op), res) -> + Some (op, res) + | _ -> + None); + proj = (fun (Activate_account_result bus) -> bus); + inj = (fun bus -> Activate_account_result bus); + } + + let proposals_case = + Case + { + op_case = Operation.Encoding.proposals_case; + encoding = Data_encoding.empty; + select = + (function + | Contents_result (Proposals_result as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result ((Proposals _ as op), res) -> + Some (op, res) + | _ -> + None); + proj = (fun Proposals_result -> ()); + inj = (fun () -> Proposals_result); + } + + let ballot_case = + Case + { + op_case = Operation.Encoding.ballot_case; + encoding = Data_encoding.empty; + select = + (function + | Contents_result (Ballot_result as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result ((Ballot _ as op), res) -> + Some (op, res) + | _ -> + None); + proj = (fun Ballot_result -> ()); + inj = (fun () -> Ballot_result); + } + + let make_manager_case (type kind) + (Operation.Encoding.Case op_case : + kind Kind.manager Operation.Encoding.case) + (Manager_result.MCase res_case : kind Manager_result.case) mselect = + Case + { + op_case = Operation.Encoding.Case op_case; + encoding = + obj3 + (req "balance_updates" Receipt.balance_updates_encoding) + (req "operation_result" res_case.t) + (dft + "internal_operation_results" + (list internal_operation_result_encoding) + []); + select = + (function + | Contents_result + (Manager_operation_result + ({operation_result = Applied res; _} as op)) -> ( + match res_case.select (Successful_manager_result res) with + | Some res -> + Some + (Manager_operation_result + {op with operation_result = Applied res}) + | None -> + None ) + | Contents_result + (Manager_operation_result + ({operation_result = Backtracked (res, errs); _} as op)) -> ( + match res_case.select (Successful_manager_result res) with + | Some res -> + Some + (Manager_operation_result + {op with operation_result = Backtracked (res, errs)}) + | None -> + None ) + | Contents_result + (Manager_operation_result + ({operation_result = Skipped kind; _} as op)) -> ( + match equal_manager_kind kind res_case.kind with + | None -> + None + | Some Eq -> + Some + (Manager_operation_result + {op with operation_result = Skipped kind}) ) + | Contents_result + (Manager_operation_result + ({operation_result = Failed (kind, errs); _} as op)) -> ( + match equal_manager_kind kind res_case.kind with + | None -> + None + | Some Eq -> + Some + (Manager_operation_result + {op with operation_result = Failed (kind, errs)}) ) + | Contents_result Ballot_result -> + None + | Contents_result (Endorsement_result _) -> + None + | Contents_result (Seed_nonce_revelation_result _) -> + None + | Contents_result (Endorsement_with_slot_result _) -> + None + | Contents_result (Double_endorsement_evidence_result _) -> + None + | Contents_result (Double_baking_evidence_result _) -> + None + | Contents_result (Activate_account_result _) -> + None + | Contents_result Proposals_result -> + None); + mselect; + proj = + (fun (Manager_operation_result + { balance_updates = bus; + operation_result = r; + internal_operation_results = rs }) -> + (bus, r, rs)); + inj = + (fun (bus, r, rs) -> + Manager_operation_result + { + balance_updates = bus; + operation_result = r; + internal_operation_results = rs; + }); + } + + let reveal_case = + make_manager_case + Operation.Encoding.reveal_case + Manager_result.reveal_case + (function + | Contents_and_result + ((Manager_operation {operation = Reveal _; _} as op), res) -> + Some (op, res) + | _ -> + None) + + let transaction_case = + make_manager_case + Operation.Encoding.transaction_case + Manager_result.transaction_case + (function + | Contents_and_result + ((Manager_operation {operation = Transaction _; _} as op), res) -> + Some (op, res) + | _ -> + None) + + let origination_case = + make_manager_case + Operation.Encoding.origination_case + Manager_result.origination_case + (function + | Contents_and_result + ((Manager_operation {operation = Origination _; _} as op), res) -> + Some (op, res) + | _ -> + None) + + let delegation_case = + make_manager_case + Operation.Encoding.delegation_case + Manager_result.delegation_case + (function + | Contents_and_result + ((Manager_operation {operation = Delegation _; _} as op), res) -> + Some (op, res) + | _ -> + None) +end + +let contents_result_encoding = + let open Encoding in + let make + (Case + { op_case = Operation.Encoding.Case {tag; name; _}; + encoding; + mselect = _; + select; + proj; + inj }) = + let proj x = + match select x with None -> None | Some x -> Some (proj x) + in + let inj x = Contents_result (inj x) in + tagged_case (Tag tag) name encoding proj inj + in + def "operation.alpha.contents_result" + @@ union + [ make endorsement_case; + make seed_nonce_revelation_case; + make endorsement_with_slot_case; + make double_endorsement_evidence_case; + make double_baking_evidence_case; + make activate_account_case; + make proposals_case; + make ballot_case; + make reveal_case; + make transaction_case; + make origination_case; + make delegation_case ] + +let contents_and_result_encoding = + let open Encoding in + let make + (Case + { op_case = Operation.Encoding.Case {tag; name; encoding; proj; inj; _}; + mselect; + encoding = meta_encoding; + proj = meta_proj; + inj = meta_inj; + _ }) = + let proj c = + match mselect c with + | Some (op, res) -> + Some (proj op, meta_proj res) + | _ -> + None + in + let inj (op, res) = Contents_and_result (inj op, meta_inj res) in + let encoding = merge_objs encoding (obj1 (req "metadata" meta_encoding)) in + tagged_case (Tag tag) name encoding proj inj + in + def "operation.alpha.operation_contents_and_result" + @@ union + [ make endorsement_case; + make seed_nonce_revelation_case; + make endorsement_with_slot_case; + make double_endorsement_evidence_case; + make double_baking_evidence_case; + make activate_account_case; + make proposals_case; + make ballot_case; + make reveal_case; + make transaction_case; + make origination_case; + make delegation_case ] + +type 'kind contents_result_list = + | Single_result : 'kind contents_result -> 'kind contents_result_list + | Cons_result : + 'kind Kind.manager contents_result + * 'rest Kind.manager contents_result_list + -> ('kind * 'rest) Kind.manager contents_result_list + +type packed_contents_result_list = + | Contents_result_list : + 'kind contents_result_list + -> packed_contents_result_list + +let contents_result_list_encoding = + let rec to_list = function + | Contents_result_list (Single_result o) -> + [Contents_result o] + | Contents_result_list (Cons_result (o, os)) -> + Contents_result o :: to_list (Contents_result_list os) + in + let rec of_list = function + | [] -> + Pervasives.failwith "cannot decode empty operation result" + | [Contents_result o] -> + Contents_result_list (Single_result o) + | Contents_result o :: os -> ( + let (Contents_result_list os) = of_list os in + match (o, os) with + | ( Manager_operation_result _, + Single_result (Manager_operation_result _) ) -> + Contents_result_list (Cons_result (o, os)) + | (Manager_operation_result _, Cons_result _) -> + Contents_result_list (Cons_result (o, os)) + | _ -> + Pervasives.failwith "cannot decode ill-formed operation result" ) + in + def "operation.alpha.contents_list_result" + @@ conv to_list of_list (list contents_result_encoding) + +type 'kind contents_and_result_list = + | Single_and_result : + 'kind Alpha_context.contents * 'kind contents_result + -> 'kind contents_and_result_list + | Cons_and_result : + 'kind Kind.manager Alpha_context.contents + * 'kind Kind.manager contents_result + * 'rest Kind.manager contents_and_result_list + -> ('kind * 'rest) Kind.manager contents_and_result_list + +type packed_contents_and_result_list = + | Contents_and_result_list : + 'kind contents_and_result_list + -> packed_contents_and_result_list + +let contents_and_result_list_encoding = + let rec to_list = function + | Contents_and_result_list (Single_and_result (op, res)) -> + [Contents_and_result (op, res)] + | Contents_and_result_list (Cons_and_result (op, res, rest)) -> + Contents_and_result (op, res) + :: to_list (Contents_and_result_list rest) + in + let rec of_list = function + | [] -> + Pervasives.failwith "cannot decode empty combined operation result" + | [Contents_and_result (op, res)] -> + Contents_and_result_list (Single_and_result (op, res)) + | Contents_and_result (op, res) :: rest -> ( + let (Contents_and_result_list rest) = of_list rest in + match (op, rest) with + | (Manager_operation _, Single_and_result (Manager_operation _, _)) -> + Contents_and_result_list (Cons_and_result (op, res, rest)) + | (Manager_operation _, Cons_and_result (_, _, _)) -> + Contents_and_result_list (Cons_and_result (op, res, rest)) + | _ -> + Pervasives.failwith + "cannot decode ill-formed combined operation result" ) + in + conv to_list of_list (Variable.list contents_and_result_encoding) + +type 'kind operation_metadata = {contents : 'kind contents_result_list} + +type packed_operation_metadata = + | Operation_metadata : 'kind operation_metadata -> packed_operation_metadata + | No_operation_metadata : packed_operation_metadata + +let operation_metadata_encoding = + def "operation.alpha.result" + @@ union + [ case + (Tag 0) + ~title:"Operation_metadata" + contents_result_list_encoding + (function + | Operation_metadata {contents} -> + Some (Contents_result_list contents) + | _ -> + None) + (fun (Contents_result_list contents) -> + Operation_metadata {contents}); + case + (Tag 1) + ~title:"No_operation_metadata" + empty + (function No_operation_metadata -> Some () | _ -> None) + (fun () -> No_operation_metadata) ] + +let kind_equal : + type kind kind2. + kind contents -> kind2 contents_result -> (kind, kind2) eq option = + fun op res -> + match (op, res) with + | (Endorsement _, Endorsement_result _) -> + Some Eq + | (Endorsement _, _) -> + None + | (Seed_nonce_revelation _, Seed_nonce_revelation_result _) -> + Some Eq + | (Seed_nonce_revelation _, _) -> + None + | (Endorsement_with_slot _, Endorsement_with_slot_result _) -> + Some Eq + | (Endorsement_with_slot _, _) -> + None + | (Double_endorsement_evidence _, Double_endorsement_evidence_result _) -> + Some Eq + | (Double_endorsement_evidence _, _) -> + None + | (Double_baking_evidence _, Double_baking_evidence_result _) -> + Some Eq + | (Double_baking_evidence _, _) -> + None + | (Activate_account _, Activate_account_result _) -> + Some Eq + | (Activate_account _, _) -> + None + | (Proposals _, Proposals_result) -> + Some Eq + | (Proposals _, _) -> + None + | (Ballot _, Ballot_result) -> + Some Eq + | (Ballot _, _) -> + None + | (Failing_noop _, _) -> + (* the Failing_noop operation always fails and can't have result *) + None + | ( Manager_operation {operation = Reveal _; _}, + Manager_operation_result {operation_result = Applied (Reveal_result _); _} + ) -> + Some Eq + | ( Manager_operation {operation = Reveal _; _}, + Manager_operation_result + {operation_result = Backtracked (Reveal_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Reveal _; _}, + Manager_operation_result + { operation_result = Failed (Alpha_context.Kind.Reveal_manager_kind, _); + _ } ) -> + Some Eq + | ( Manager_operation {operation = Reveal _; _}, + Manager_operation_result + {operation_result = Skipped Alpha_context.Kind.Reveal_manager_kind; _} + ) -> + Some Eq + | (Manager_operation {operation = Reveal _; _}, _) -> + None + | ( Manager_operation {operation = Transaction _; _}, + Manager_operation_result + {operation_result = Applied (Transaction_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Transaction _; _}, + Manager_operation_result + {operation_result = Backtracked (Transaction_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Transaction _; _}, + Manager_operation_result + { operation_result = + Failed (Alpha_context.Kind.Transaction_manager_kind, _); + _ } ) -> + Some Eq + | ( Manager_operation {operation = Transaction _; _}, + Manager_operation_result + { operation_result = Skipped Alpha_context.Kind.Transaction_manager_kind; + _ } ) -> + Some Eq + | (Manager_operation {operation = Transaction _; _}, _) -> + None + | ( Manager_operation {operation = Origination _; _}, + Manager_operation_result + {operation_result = Applied (Origination_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Origination _; _}, + Manager_operation_result + {operation_result = Backtracked (Origination_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Origination _; _}, + Manager_operation_result + { operation_result = + Failed (Alpha_context.Kind.Origination_manager_kind, _); + _ } ) -> + Some Eq + | ( Manager_operation {operation = Origination _; _}, + Manager_operation_result + { operation_result = Skipped Alpha_context.Kind.Origination_manager_kind; + _ } ) -> + Some Eq + | (Manager_operation {operation = Origination _; _}, _) -> + None + | ( Manager_operation {operation = Delegation _; _}, + Manager_operation_result + {operation_result = Applied (Delegation_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Delegation _; _}, + Manager_operation_result + {operation_result = Backtracked (Delegation_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Delegation _; _}, + Manager_operation_result + { operation_result = + Failed (Alpha_context.Kind.Delegation_manager_kind, _); + _ } ) -> + Some Eq + | ( Manager_operation {operation = Delegation _; _}, + Manager_operation_result + { operation_result = Skipped Alpha_context.Kind.Delegation_manager_kind; + _ } ) -> + Some Eq + | (Manager_operation {operation = Delegation _; _}, _) -> + None + +let rec kind_equal_list : + type kind kind2. + kind contents_list -> kind2 contents_result_list -> (kind, kind2) eq option + = + fun contents res -> + match (contents, res) with + | (Single op, Single_result res) -> ( + match kind_equal op res with None -> None | Some Eq -> Some Eq ) + | (Cons (op, ops), Cons_result (res, ress)) -> ( + match kind_equal op res with + | None -> + None + | Some Eq -> ( + match kind_equal_list ops ress with None -> None | Some Eq -> Some Eq ) ) + | _ -> + None + +let rec pack_contents_list : + type kind. + kind contents_list -> + kind contents_result_list -> + kind contents_and_result_list = + fun contents res -> + match (contents, res) with + | (Single op, Single_result res) -> + Single_and_result (op, res) + | (Cons (op, ops), Cons_result (res, ress)) -> + Cons_and_result (op, res, pack_contents_list ops ress) + | ( Single (Manager_operation _), + Cons_result (Manager_operation_result _, Single_result _) ) -> + . + | ( Cons (_, _), + Single_result (Manager_operation_result {operation_result = Failed _; _}) + ) -> + . + | ( Cons (_, _), + Single_result + (Manager_operation_result {operation_result = Skipped _; _}) ) -> + . + | ( Cons (_, _), + Single_result + (Manager_operation_result {operation_result = Applied _; _}) ) -> + . + | ( Cons (_, _), + Single_result + (Manager_operation_result {operation_result = Backtracked _; _}) ) -> + . + | (Single _, Cons_result _) -> + . + +let rec unpack_contents_list : + type kind. + kind contents_and_result_list -> + kind contents_list * kind contents_result_list = function + | Single_and_result (op, res) -> + (Single op, Single_result res) + | Cons_and_result (op, res, rest) -> + let (ops, ress) = unpack_contents_list rest in + (Cons (op, ops), Cons_result (res, ress)) + +let rec to_list = function + | Contents_result_list (Single_result o) -> + [Contents_result o] + | Contents_result_list (Cons_result (o, os)) -> + Contents_result o :: to_list (Contents_result_list os) + +let rec of_list = function + | [] -> + assert false + | [Contents_result o] -> + Contents_result_list (Single_result o) + | Contents_result o :: os -> ( + let (Contents_result_list os) = of_list os in + match (o, os) with + | (Manager_operation_result _, Single_result (Manager_operation_result _)) + -> + Contents_result_list (Cons_result (o, os)) + | (Manager_operation_result _, Cons_result _) -> + Contents_result_list (Cons_result (o, os)) + | _ -> + Pervasives.failwith + "Operation result list of length > 1 should only contains manager \ + operations result." ) + +let operation_data_and_metadata_encoding = + def "operation.alpha.operation_with_metadata" + @@ union + [ case + (Tag 0) + ~title:"Operation_with_metadata" + (obj2 + (req "contents" (dynamic_size contents_and_result_list_encoding)) + (opt "signature" Signature.encoding)) + (function + | (Operation_data _, No_operation_metadata) -> + None + | (Operation_data op, Operation_metadata res) -> ( + match kind_equal_list op.contents res.contents with + | None -> + Pervasives.failwith + "cannot decode inconsistent combined operation result" + | Some Eq -> + Some + ( Contents_and_result_list + (pack_contents_list op.contents res.contents), + op.signature ) )) + (fun (Contents_and_result_list contents, signature) -> + let (op_contents, res_contents) = unpack_contents_list contents in + ( Operation_data {contents = op_contents; signature}, + Operation_metadata {contents = res_contents} )); + case + (Tag 1) + ~title:"Operation_without_metadata" + (obj2 + (req "contents" (dynamic_size Operation.contents_list_encoding)) + (opt "signature" Signature.encoding)) + (function + | (Operation_data op, No_operation_metadata) -> + Some (Contents_list op.contents, op.signature) + | (Operation_data _, Operation_metadata _) -> + None) + (fun (Contents_list contents, signature) -> + (Operation_data {contents; signature}, No_operation_metadata)) ] + +type block_metadata = { + baker : Signature.Public_key_hash.t; + level : Level.compat_t; + level_info : Level.t; + voting_period_kind : Voting_period.kind; + voting_period_info : Voting_period.info; + nonce_hash : Nonce_hash.t option; + consumed_gas : Gas.Arith.fp; + deactivated : Signature.Public_key_hash.t list; + balance_updates : Receipt.balance_updates; +} + +let block_metadata_encoding = + let open Data_encoding in + def "block_header.alpha.metadata" + @@ conv + (fun { baker; + level; + level_info; + voting_period_kind; + voting_period_info; + nonce_hash; + consumed_gas; + deactivated; + balance_updates } -> + ( baker, + level, + level_info, + voting_period_kind, + voting_period_info, + nonce_hash, + consumed_gas, + deactivated, + balance_updates )) + (fun ( baker, + level, + level_info, + voting_period_kind, + voting_period_info, + nonce_hash, + consumed_gas, + deactivated, + balance_updates ) -> + { + baker; + level; + level_info; + voting_period_kind; + voting_period_info; + nonce_hash; + consumed_gas; + deactivated; + balance_updates; + }) + (obj9 + (req "baker" Signature.Public_key_hash.encoding) + (req + ~description:"This field is DEPRECATED: use level_info instead" + "level" + Level.compat_encoding) + (req "level_info" Level.encoding) + (req + ~description: + "This field is DEPRECATED: use voting_period_info instead" + "voting_period_kind" + Voting_period.kind_encoding) + (req "voting_period_info" Voting_period.info_encoding) + (req "nonce_hash" (option Nonce_hash.encoding)) + (req "consumed_gas" Gas.Arith.n_fp_encoding) + (req "deactivated" (list Signature.Public_key_hash.encoding)) + (req "balance_updates" Receipt.balance_updates_encoding)) diff --git a/src/proto_009_PsFLoren/lib_protocol/apply_results.mli b/src/proto_009_PsFLoren/lib_protocol/apply_results.mli new file mode 100644 index 0000000000000000000000000000000000000000..ac2877daa1c6d8ccab23bfd232f1c558e9978baf --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/apply_results.mli @@ -0,0 +1,196 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Result of applying an operation, can be used for experimenting + with protocol updates, by clients to print out a summary of the + operation at pre-injection simulation and at confirmation time, + and by block explorers. *) + +open Alpha_context + +(** Result of applying a {!Operation.t}. Follows the same structure. *) +type 'kind operation_metadata = {contents : 'kind contents_result_list} + +and packed_operation_metadata = + | Operation_metadata : 'kind operation_metadata -> packed_operation_metadata + | No_operation_metadata : packed_operation_metadata + +(** Result of applying a {!Operation.contents_list}. Follows the same structure. *) +and 'kind contents_result_list = + | Single_result : 'kind contents_result -> 'kind contents_result_list + | Cons_result : + 'kind Kind.manager contents_result + * 'rest Kind.manager contents_result_list + -> ('kind * 'rest) Kind.manager contents_result_list + +and packed_contents_result_list = + | Contents_result_list : + 'kind contents_result_list + -> packed_contents_result_list + +(** Result of applying an {!Operation.contents}. Follows the same structure. *) +and 'kind contents_result = + | Endorsement_result : { + balance_updates : Receipt.balance_updates; + delegate : Signature.Public_key_hash.t; + slots : int list; + } + -> Kind.endorsement contents_result + | Seed_nonce_revelation_result : + Receipt.balance_updates + -> Kind.seed_nonce_revelation contents_result + | Endorsement_with_slot_result : + Kind.endorsement contents_result + -> Kind.endorsement_with_slot contents_result + | Double_endorsement_evidence_result : + Receipt.balance_updates + -> Kind.double_endorsement_evidence contents_result + | Double_baking_evidence_result : + Receipt.balance_updates + -> Kind.double_baking_evidence contents_result + | Activate_account_result : + Receipt.balance_updates + -> Kind.activate_account contents_result + | Proposals_result : Kind.proposals contents_result + | Ballot_result : Kind.ballot contents_result + | Manager_operation_result : { + balance_updates : Receipt.balance_updates; + operation_result : 'kind manager_operation_result; + internal_operation_results : packed_internal_operation_result list; + } + -> 'kind Kind.manager contents_result + +and packed_contents_result = + | Contents_result : 'kind contents_result -> packed_contents_result + +(** The result of an operation in the queue. [Skipped] ones should + always be at the tail, and after a single [Failed]. *) +and 'kind manager_operation_result = + | Applied of 'kind successful_manager_operation_result + | Backtracked of + 'kind successful_manager_operation_result * error trace option + | Failed : 'kind Kind.manager * error trace -> 'kind manager_operation_result + | Skipped : 'kind Kind.manager -> 'kind manager_operation_result +[@@coq_force_gadt] + +(** Result of applying a {!manager_operation_content}, either internal + or external. *) +and _ successful_manager_operation_result = + | Reveal_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.reveal successful_manager_operation_result + | Transaction_result : { + storage : Script.expr option; + lazy_storage_diff : Lazy_storage.diffs option; + balance_updates : Receipt.balance_updates; + originated_contracts : Contract.t list; + consumed_gas : Gas.Arith.fp; + storage_size : Z.t; + paid_storage_size_diff : Z.t; + allocated_destination_contract : bool; + } + -> Kind.transaction successful_manager_operation_result + | Origination_result : { + lazy_storage_diff : Lazy_storage.diffs option; + balance_updates : Receipt.balance_updates; + originated_contracts : Contract.t list; + consumed_gas : Gas.Arith.fp; + storage_size : Z.t; + paid_storage_size_diff : Z.t; + } + -> Kind.origination successful_manager_operation_result + | Delegation_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.delegation successful_manager_operation_result + +and packed_successful_manager_operation_result = + | Successful_manager_result : + 'kind successful_manager_operation_result + -> packed_successful_manager_operation_result + +and packed_internal_operation_result = + | Internal_operation_result : + 'kind internal_operation * 'kind manager_operation_result + -> packed_internal_operation_result + +(** Serializer for {!packed_operation_result}. *) +val operation_metadata_encoding : packed_operation_metadata Data_encoding.t + +val operation_data_and_metadata_encoding : + (Operation.packed_protocol_data * packed_operation_metadata) Data_encoding.t + +type 'kind contents_and_result_list = + | Single_and_result : + 'kind Alpha_context.contents * 'kind contents_result + -> 'kind contents_and_result_list + | Cons_and_result : + 'kind Kind.manager Alpha_context.contents + * 'kind Kind.manager contents_result + * 'rest Kind.manager contents_and_result_list + -> ('kind * 'rest) Kind.manager contents_and_result_list + +type packed_contents_and_result_list = + | Contents_and_result_list : + 'kind contents_and_result_list + -> packed_contents_and_result_list + +val contents_and_result_list_encoding : + packed_contents_and_result_list Data_encoding.t + +val pack_contents_list : + 'kind contents_list -> + 'kind contents_result_list -> + 'kind contents_and_result_list + +val unpack_contents_list : + 'kind contents_and_result_list -> + 'kind contents_list * 'kind contents_result_list + +val to_list : packed_contents_result_list -> packed_contents_result list + +val of_list : packed_contents_result list -> packed_contents_result_list + +type ('a, 'b) eq = Eq : ('a, 'a) eq + +val kind_equal_list : + 'kind contents_list -> + 'kind2 contents_result_list -> + ('kind, 'kind2) eq option + +type block_metadata = { + baker : Signature.Public_key_hash.t; + level : Level.compat_t; + level_info : Level.t; + voting_period_kind : Voting_period.kind; + voting_period_info : Voting_period.info; + nonce_hash : Nonce_hash.t option; + consumed_gas : Gas.Arith.fp; + deactivated : Signature.Public_key_hash.t list; + balance_updates : Receipt.balance_updates; +} + +val block_metadata_encoding : block_metadata Data_encoding.encoding diff --git a/src/proto_009_PsFLoren/lib_protocol/baking.ml b/src/proto_009_PsFLoren/lib_protocol/baking.ml new file mode 100644 index 0000000000000000000000000000000000000000..8b9243f64c3c4a08a7bcfdfa0b6e8ad96ea10610 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/baking.ml @@ -0,0 +1,432 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Misc + +type error += Invalid_fitness_gap of int64 * int64 (* `Permanent *) + +type error += Timestamp_too_early of Timestamp.t * Timestamp.t + +(* `Permanent *) + +type error += Unexpected_endorsement (* `Permanent *) + +type error += Invalid_endorsement_slot of int (* `Permanent *) + +type error += Unexpected_endorsement_slot of int (* `Permanent *) + +type error += + | Invalid_block_signature of Block_hash.t * Signature.Public_key_hash.t + +(* `Permanent *) + +type error += Invalid_signature (* `Permanent *) + +type error += Invalid_stamp (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"baking.timestamp_too_early" + ~title:"Block forged too early" + ~description: + "The block timestamp is before the first slot for this baker at this \ + level" + ~pp:(fun ppf (r, p) -> + Format.fprintf + ppf + "Block forged too early (%a is before %a)" + Time.pp_hum + p + Time.pp_hum + r) + Data_encoding.( + obj2 (req "minimum" Time.encoding) (req "provided" Time.encoding)) + (function Timestamp_too_early (r, p) -> Some (r, p) | _ -> None) + (fun (r, p) -> Timestamp_too_early (r, p)) ; + register_error_kind + `Permanent + ~id:"baking.invalid_fitness_gap" + ~title:"Invalid fitness gap" + ~description:"The gap of fitness is out of bounds" + ~pp:(fun ppf (m, g) -> + Format.fprintf ppf "The gap of fitness %Ld is not between 0 and %Ld" g m) + Data_encoding.(obj2 (req "maximum" int64) (req "provided" int64)) + (function Invalid_fitness_gap (m, g) -> Some (m, g) | _ -> None) + (fun (m, g) -> Invalid_fitness_gap (m, g)) ; + register_error_kind + `Permanent + ~id:"baking.invalid_block_signature" + ~title:"Invalid block signature" + ~description:"A block was not signed with the expected private key." + ~pp:(fun ppf (block, pkh) -> + Format.fprintf + ppf + "Invalid signature for block %a. Expected: %a." + Block_hash.pp_short + block + Signature.Public_key_hash.pp_short + pkh) + Data_encoding.( + obj2 + (req "block" Block_hash.encoding) + (req "expected" Signature.Public_key_hash.encoding)) + (function + | Invalid_block_signature (block, pkh) -> Some (block, pkh) | _ -> None) + (fun (block, pkh) -> Invalid_block_signature (block, pkh)) ; + register_error_kind + `Permanent + ~id:"baking.invalid_signature" + ~title:"Invalid block signature" + ~description:"The block's signature is invalid" + ~pp:(fun ppf () -> Format.fprintf ppf "Invalid block signature") + Data_encoding.empty + (function Invalid_signature -> Some () | _ -> None) + (fun () -> Invalid_signature) ; + register_error_kind + `Permanent + ~id:"baking.insufficient_proof_of_work" + ~title:"Insufficient block proof-of-work stamp" + ~description:"The block's proof-of-work stamp is insufficient" + ~pp:(fun ppf () -> Format.fprintf ppf "Insufficient proof-of-work stamp") + Data_encoding.empty + (function Invalid_stamp -> Some () | _ -> None) + (fun () -> Invalid_stamp) ; + register_error_kind + `Permanent + ~id:"baking.unexpected_endorsement" + ~title:"Endorsement from unexpected delegate" + ~description: + "The operation is signed by a delegate without endorsement rights." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The endorsement is signed by a delegate without endorsement rights.") + Data_encoding.unit + (function Unexpected_endorsement -> Some () | _ -> None) + (fun () -> Unexpected_endorsement) ; + register_error_kind + `Permanent + ~id:"baking.invalid_endorsement_slot" + ~title:"Endorsement slot out of range" + ~description:"The endorsement slot provided is negative or too high." + ~pp:(fun ppf v -> + Format.fprintf + ppf + "Endorsement slot %d provided is negative or too high." + v) + Data_encoding.(obj1 (req "slot" uint16)) + (function Invalid_endorsement_slot v -> Some v | _ -> None) + (fun v -> Invalid_endorsement_slot v) ; + register_error_kind + `Permanent + ~id:"baking.unexpected_endorsement_slot" + ~title:"Endorsement slot not the smallest possible" + ~description:"The endorsement slot provided is not the smallest possible." + ~pp:(fun ppf v -> + Format.fprintf + ppf + "Endorsement slot %d provided is not the smallest possible." + v) + Data_encoding.(obj1 (req "slot" uint16)) + (function Unexpected_endorsement_slot v -> Some v | _ -> None) + (fun v -> Unexpected_endorsement_slot v) + +let minimal_time c priority pred_timestamp = + let priority = Int32.of_int priority in + let rec cumsum_time_between_blocks acc durations p = + if Compare.Int32.( <= ) p 0l then ok acc + else + match durations with + | [] -> + cumsum_time_between_blocks acc [Period.one_minute] p + | [last] -> + Period.mult p last >>? fun period -> Timestamp.(acc +? period) + | first :: durations -> + Timestamp.(acc +? first) + >>? fun acc -> + let p = Int32.pred p in + cumsum_time_between_blocks acc durations p + in + cumsum_time_between_blocks + pred_timestamp + (Constants.time_between_blocks c) + (Int32.succ priority) + +let earlier_predecessor_timestamp ctxt level = + let current = Level.current ctxt in + let current_timestamp = Timestamp.current ctxt in + let gap = Level.diff level current in + let step = List.hd (Constants.time_between_blocks ctxt) in + if Compare.Int32.(gap < 1l) then + failwith "Baking.earlier_block_timestamp: past block." + else + Period.mult (Int32.pred gap) step + >>? fun delay -> Timestamp.(current_timestamp +? delay) + +let check_timestamp c priority pred_timestamp = + minimal_time c priority pred_timestamp + >>? fun minimal_time -> + let timestamp = Alpha_context.Timestamp.current c in + record_trace + (Timestamp_too_early (minimal_time, timestamp)) + Timestamp.(timestamp -? minimal_time) + +let check_baking_rights c {Block_header.priority; _} pred_timestamp = + let level = Level.current c in + Roll.baking_rights_owner c level ~priority + >>=? fun delegate -> + Lwt.return + ( check_timestamp c priority pred_timestamp + >|? fun block_delay -> (delegate, block_delay) ) + +type error += Incorrect_priority (* `Permanent *) + +type error += Incorrect_number_of_endorsements (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"incorrect_priority" + ~title:"Incorrect priority" + ~description:"Block priority must be non-negative." + ~pp:(fun ppf () -> + Format.fprintf ppf "The block priority must be non-negative.") + Data_encoding.unit + (function Incorrect_priority -> Some () | _ -> None) + (fun () -> Incorrect_priority) + +let () = + let description = + "The number of endorsements must be non-negative and at most the \ + endorsers_per_block constant." + in + register_error_kind + `Permanent + ~id:"incorrect_number_of_endorsements" + ~title:"Incorrect number of endorsements" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Incorrect_number_of_endorsements -> Some () | _ -> None) + (fun () -> Incorrect_number_of_endorsements) + +let rec reward_for_priority reward_per_prio prio = + match reward_per_prio with + | [] -> + (* Empty reward list in parameters means no rewards *) + Tez.zero + | [last] -> + last + | first :: rest -> + if Compare.Int.(prio <= 0) then first + else reward_for_priority rest (pred prio) + +let baking_reward ctxt ~block_priority ~included_endorsements = + error_unless Compare.Int.(block_priority >= 0) Incorrect_priority + >>? fun () -> + error_unless + Compare.Int.( + included_endorsements >= 0 + && included_endorsements <= Constants.endorsers_per_block ctxt) + Incorrect_number_of_endorsements + >>? fun () -> + let reward_per_endorsement = + reward_for_priority + (Constants.baking_reward_per_endorsement ctxt) + block_priority + in + Tez.(reward_per_endorsement *? Int64.of_int included_endorsements) + +let endorsing_reward ctxt ~block_priority num_slots = + error_unless Compare.Int.(block_priority >= 0) Incorrect_priority + >>? fun () -> + let reward_per_endorsement = + reward_for_priority (Constants.endorsement_reward ctxt) block_priority + in + Tez.(reward_per_endorsement *? Int64.of_int num_slots) + +let baking_priorities c level = + let rec f priority = + Roll.baking_rights_owner c level ~priority + >|=? fun delegate -> LCons (delegate, fun () -> f (succ priority)) + in + f 0 + +let endorsement_rights ctxt level = + fold_right_s + (fun slot acc -> + Roll.endorsement_rights_owner ctxt level ~slot + >|=? fun pk -> + let pkh = Signature.Public_key.hash pk in + let right = + match Signature.Public_key_hash.Map.find_opt pkh acc with + | None -> + (pk, [slot], false) + | Some (pk, slots, used) -> + (pk, slot :: slots, used) + in + Signature.Public_key_hash.Map.add pkh right acc) + (0 --> (Constants.endorsers_per_block ctxt - 1)) + Signature.Public_key_hash.Map.empty + +let check_endorsement_rights ctxt chain_id ~slot + (op : Kind.endorsement Operation.t) = + if + Compare.Int.(slot < 0 (* should not happen because of binary format *)) + || Compare.Int.(slot >= Constants.endorsers_per_block ctxt) + then fail (Invalid_endorsement_slot slot) + else + let current_level = Level.current ctxt in + let (Single (Endorsement {level; _})) = op.protocol_data.contents in + Roll.endorsement_rights_owner ctxt (Level.from_raw ctxt level) ~slot + >>=? fun pk -> + let pkh = Signature.Public_key.hash pk in + match Operation.check_signature pk chain_id op with + | Error _ -> + fail Unexpected_endorsement + | Ok () -> ( + ( if Raw_level.(succ level = current_level.level) then + return (Alpha_context.allowed_endorsements ctxt) + else endorsement_rights ctxt (Level.from_raw ctxt level) ) + >>=? fun endorsements -> + match Signature.Public_key_hash.Map.find_opt pkh endorsements with + | None -> + fail Unexpected_endorsement (* unexpected *) + | Some (_pk, slots, v) -> + error_unless + Compare.Int.(slot = List.hd slots) + (Unexpected_endorsement_slot slot) + >>?= fun () -> return (pkh, slots, v) ) + +let select_delegate delegate delegate_list max_priority = + let rec loop acc l n = + if Compare.Int.(n >= max_priority) then return (List.rev acc) + else + let (LCons (pk, t)) = l in + let acc = + if + Signature.Public_key_hash.equal + delegate + (Signature.Public_key.hash pk) + then n :: acc + else acc + in + t () >>=? fun t -> loop acc t (succ n) + in + loop [] delegate_list 0 + +let first_baking_priorities ctxt ?(max_priority = 32) delegate level = + baking_priorities ctxt level + >>=? fun delegate_list -> select_delegate delegate delegate_list max_priority + +let check_hash hash stamp_threshold = + let bytes = Block_hash.to_bytes hash in + let word = TzEndian.get_int64 bytes 0 in + Compare.Uint64.(word <= stamp_threshold) + +let check_header_proof_of_work_stamp shell contents stamp_threshold = + let hash = + Block_header.hash + {shell; protocol_data = {contents; signature = Signature.zero}} + in + check_hash hash stamp_threshold + +let check_proof_of_work_stamp ctxt block = + let proof_of_work_threshold = Constants.proof_of_work_threshold ctxt in + if + check_header_proof_of_work_stamp + block.Block_header.shell + block.protocol_data.contents + proof_of_work_threshold + then ok_unit + else error Invalid_stamp + +let check_signature block chain_id key = + let check_signature key + {Block_header.shell; protocol_data = {contents; signature}} = + let unsigned_header = + Data_encoding.Binary.to_bytes_exn + Block_header.unsigned_encoding + (shell, contents) + in + Signature.check + ~watermark:(Block_header chain_id) + key + signature + unsigned_header + in + if check_signature key block then return_unit + else + fail + (Invalid_block_signature + (Block_header.hash block, Signature.Public_key.hash key)) + +let max_fitness_gap _ctxt = 1L + +let check_fitness_gap ctxt (block : Block_header.t) = + let current_fitness = Fitness.current ctxt in + Fitness.to_int64 block.shell.fitness + >>? fun announced_fitness -> + let gap = Int64.sub announced_fitness current_fitness in + if Compare.Int64.(gap <= 0L || max_fitness_gap ctxt < gap) then + error (Invalid_fitness_gap (max_fitness_gap ctxt, gap)) + else ok_unit + +let last_of_a_cycle ctxt (l : Level.t) = + Compare.Int32.( + Int32.succ l.Level.cycle_position = Constants.blocks_per_cycle ctxt) + +let dawn_of_a_new_cycle ctxt = + let level = Level.current ctxt in + if last_of_a_cycle ctxt level then Some level.cycle else None + +let minimum_allowed_endorsements ctxt ~block_delay = + let minimum = Constants.initial_endorsers ctxt in + let delay_per_missing_endorsement = + Period.to_seconds (Constants.delay_per_missing_endorsement ctxt) + in + let reduced_time_constraint = + let delay = Period.to_seconds block_delay in + if Compare.Int64.(delay_per_missing_endorsement = 0L) then delay + else Int64.div delay delay_per_missing_endorsement + in + if Compare.Int64.(Int64.of_int minimum < reduced_time_constraint) then 0 + else minimum - Int64.to_int reduced_time_constraint + +let minimal_valid_time ctxt ~priority ~endorsing_power = + let predecessor_timestamp = Timestamp.current ctxt in + minimal_time ctxt priority predecessor_timestamp + >>? fun minimal_time -> + let minimal_required_endorsements = Constants.initial_endorsers ctxt in + let delay_per_missing_endorsement = + Constants.delay_per_missing_endorsement ctxt + in + let missing_endorsements = + Compare.Int.max 0 (minimal_required_endorsements - endorsing_power) + in + Period.mult (Int32.of_int missing_endorsements) delay_per_missing_endorsement + >|? fun delay -> Time.add minimal_time (Period.to_seconds delay) diff --git a/src/proto_009_PsFLoren/lib_protocol/baking.mli b/src/proto_009_PsFLoren/lib_protocol/baking.mli new file mode 100644 index 0000000000000000000000000000000000000000..a6eaee1da518141a2d35f5203e59a7f7e9d90c68 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/baking.mli @@ -0,0 +1,164 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Misc + +type error += Invalid_fitness_gap of int64 * int64 (* `Permanent *) + +type error += Timestamp_too_early of Timestamp.t * Timestamp.t + +(* `Permanent *) + +type error += + | Invalid_block_signature of Block_hash.t * Signature.Public_key_hash.t + +(* `Permanent *) + +type error += Unexpected_endorsement (* `Permanent *) + +type error += Invalid_endorsement_slot of int (* `Permanent *) + +type error += Unexpected_endorsement_slot of int (* `Permanent *) + +type error += Invalid_signature (* `Permanent *) + +type error += Invalid_stamp (* `Permanent *) + +(** [minimal_time ctxt priority pred_block_time] returns the minimal + time, given the predecessor block timestamp [pred_block_time], + after which a baker with priority [priority] is allowed to + bake. Fail with [Invalid_time_between_blocks_constant] if the minimal + time cannot be computed. *) +val minimal_time : context -> int -> Time.t -> Time.t tzresult + +(** [check_baking_rights ctxt block pred_timestamp] verifies that: + * the contract that owned the roll at cycle start has the block signer as delegate. + * the timestamp is coherent with the announced slot. +*) +val check_baking_rights : + context -> + Block_header.contents -> + Time.t -> + (public_key * Period.t) tzresult Lwt.t + +(** For a given level computes who has the right to + include an endorsement in the next block. + The result can be stored in Alpha_context.allowed_endorsements *) +val endorsement_rights : + context -> + Level.t -> + (public_key * int list * bool) Signature.Public_key_hash.Map.t tzresult Lwt.t + +(** Check that the operation was signed by a the delegate allowed to + endorse at the given slot and at the level specified by the + endorsement. The slot should be the smallest among the delegate's + slots. *) +val check_endorsement_rights : + context -> + Chain_id.t -> + slot:int -> + Kind.endorsement Operation.t -> + (public_key_hash * int list * bool) tzresult Lwt.t + +(** Returns the baking reward calculated w.r.t a given priority [p] and a + number [e] of included endorsements *) +val baking_reward : + context -> block_priority:int -> included_endorsements:int -> Tez.t tzresult + +(** Returns the endorsing reward calculated w.r.t a given priority. *) +val endorsing_reward : context -> block_priority:int -> int -> Tez.t tzresult + +(** [baking_priorities ctxt level] is the lazy list of contract's + public key hashes that are allowed to bake for [level]. *) +val baking_priorities : context -> Level.t -> public_key lazy_list + +(** [first_baking_priorities ctxt ?max_priority contract_hash level] + is a list of priorities of max [?max_priority] elements, where the + delegate of [contract_hash] is allowed to bake for [level]. If + [?max_priority] is [None], a sensible number of priorities is + returned. *) +val first_baking_priorities : + context -> + ?max_priority:int -> + public_key_hash -> + Level.t -> + int list tzresult Lwt.t + +(** [check_signature ctxt chain_id block id] check if the block is + signed with the given key, and belongs to the given [chain_id] *) +val check_signature : + Block_header.t -> Chain_id.t -> public_key -> unit tzresult Lwt.t + +(** Checks if the header that would be built from the given components + is valid for the given difficulty. The signature is not passed as it + is does not impact the proof-of-work stamp. The stamp is checked on + the hash of a block header whose signature has been zeroed-out. *) +val check_header_proof_of_work_stamp : + Block_header.shell_header -> Block_header.contents -> int64 -> bool + +(** verify if the proof of work stamp is valid *) +val check_proof_of_work_stamp : context -> Block_header.t -> unit tzresult + +(** check if the gap between the fitness of the current context + and the given block is within the protocol parameters *) +val check_fitness_gap : context -> Block_header.t -> unit tzresult + +val dawn_of_a_new_cycle : context -> Cycle.t option + +val earlier_predecessor_timestamp : context -> Level.t -> Timestamp.t tzresult + +(** Since Emmy+ + + A block is valid only if its timestamp has a minimal delay with + respect to the previous block's timestamp, and this minimal delay + depends not only on the block's priority but also on the number of + endorsement operations included in the block. + + In Emmy+, blocks' fitness increases by one unit with each level. + + In this way, Emmy+ simplifies the optimal baking strategy: The + bakers used to have to choose whether to wait for more endorsements + to include in their block, or to publish the block immediately, + without waiting. The incentive for including more endorsements was + to increase the fitness and win against unknown blocks. However, + when a block was produced too late in the priority period, there + was the risk that the block did not reach endorsers before the + block of next priority. In Emmy+, the baker does not need to take + such a decision, because the baker cannot publish a block too + early. *) + +(** Given a delay of a block's timestamp with respect to the minimum + time to bake at the block's priority (as returned by + `minimum_time`), it returns the minimum number of endorsements that + the block has to contain *) +val minimum_allowed_endorsements : context -> block_delay:Period.t -> int + +(** This is the somehow the dual of the previous function. Given a + block priority and a number of endorsement slots (given by the + `endorsing_power` argument), it returns the minimum time at which + the next block can be baked. *) +val minimal_valid_time : + context -> priority:int -> endorsing_power:int -> Time.t tzresult diff --git a/src/proto_009_PsFLoren/lib_protocol/blinded_public_key_hash.ml b/src/proto_009_PsFLoren/lib_protocol/blinded_public_key_hash.ml new file mode 100644 index 0000000000000000000000000000000000000000..f171500e402f0eb0db17ac62357d1dcbd70e1cdb --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/blinded_public_key_hash.ml @@ -0,0 +1,57 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module H = + Blake2B.Make + (Base58) + (struct + let name = "Blinded public key hash" + + let title = "A blinded public key hash" + + let b58check_prefix = "\001\002\049\223" + + let size = Some Ed25519.Public_key_hash.size + end) + +include H + +let () = Base58.check_encoded_prefix b58check_encoding "btz1" 37 + +let of_ed25519_pkh activation_code pkh = + hash_bytes ~key:activation_code [Ed25519.Public_key_hash.to_bytes pkh] + +type activation_code = bytes + +let activation_code_size = Ed25519.Public_key_hash.size + +let activation_code_encoding = Data_encoding.Fixed.bytes activation_code_size + +let activation_code_of_hex h = + if Compare.Int.(String.length h <> activation_code_size * 2) then + invalid_arg "Blinded_public_key_hash.activation_code_of_hex" ; + Hex.to_bytes (`Hex h) + +module Index = H diff --git a/src/proto_009_PsFLoren/lib_protocol/blinded_public_key_hash.mli b/src/proto_009_PsFLoren/lib_protocol/blinded_public_key_hash.mli new file mode 100644 index 0000000000000000000000000000000000000000..6d9ccfc2d1ee536ff9de8fb8a99072e769e05cd3 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/blinded_public_key_hash.mli @@ -0,0 +1,36 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include S.HASH + +type activation_code + +val activation_code_encoding : activation_code Data_encoding.t + +val of_ed25519_pkh : activation_code -> Ed25519.Public_key_hash.t -> t + +val activation_code_of_hex : string -> activation_code + +module Index : Storage_description.INDEX with type t = t diff --git a/src/proto_009_PsFLoren/lib_protocol/block_header_repr.ml b/src/proto_009_PsFLoren/lib_protocol/block_header_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..faf827278a93f29888bc1be9b967581fe91e74c7 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/block_header_repr.ml @@ -0,0 +1,130 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Block header *) + +type contents = { + priority : int; + seed_nonce_hash : Nonce_hash.t option; + proof_of_work_nonce : bytes; +} + +type protocol_data = {contents : contents; signature : Signature.t} + +type t = {shell : Block_header.shell_header; protocol_data : protocol_data} + +type block_header = t + +type raw = Block_header.t + +type shell_header = Block_header.shell_header + +let raw_encoding = Block_header.encoding + +let shell_header_encoding = Block_header.shell_header_encoding + +let contents_encoding = + let open Data_encoding in + def "block_header.alpha.unsigned_contents" + @@ conv + (fun {priority; seed_nonce_hash; proof_of_work_nonce} -> + (priority, proof_of_work_nonce, seed_nonce_hash)) + (fun (priority, proof_of_work_nonce, seed_nonce_hash) -> + {priority; seed_nonce_hash; proof_of_work_nonce}) + (obj3 + (req "priority" uint16) + (req + "proof_of_work_nonce" + (Fixed.bytes Constants_repr.proof_of_work_nonce_size)) + (opt "seed_nonce_hash" Nonce_hash.encoding)) + +let protocol_data_encoding = + let open Data_encoding in + def "block_header.alpha.signed_contents" + @@ conv + (fun {contents; signature} -> (contents, signature)) + (fun (contents, signature) -> {contents; signature}) + (merge_objs + contents_encoding + (obj1 (req "signature" Signature.encoding))) + +let raw {shell; protocol_data} = + let protocol_data = + Data_encoding.Binary.to_bytes_exn protocol_data_encoding protocol_data + in + {Block_header.shell; protocol_data} + +let unsigned_encoding = + let open Data_encoding in + merge_objs Block_header.shell_header_encoding contents_encoding + +let encoding = + let open Data_encoding in + def "block_header.alpha.full_header" + @@ conv + (fun {shell; protocol_data} -> (shell, protocol_data)) + (fun (shell, protocol_data) -> {shell; protocol_data}) + (merge_objs Block_header.shell_header_encoding protocol_data_encoding) + +(** Constants *) + +let max_header_length = + let fake_shell = + { + Block_header.level = 0l; + proto_level = 0; + predecessor = Block_hash.zero; + timestamp = Time.of_seconds 0L; + validation_passes = 0; + operations_hash = Operation_list_list_hash.zero; + fitness = Fitness_repr.from_int64 0L; + context = Context_hash.zero; + } + and fake_contents = + { + priority = 0; + proof_of_work_nonce = + Bytes.make Constants_repr.proof_of_work_nonce_size '0'; + seed_nonce_hash = Some Nonce_hash.zero; + } + in + Data_encoding.Binary.length + encoding + { + shell = fake_shell; + protocol_data = {contents = fake_contents; signature = Signature.zero}; + } + +(** Header parsing entry point *) + +let hash_raw = Block_header.hash + +let hash {shell; protocol_data} = + Block_header.hash + { + shell; + protocol_data = + Data_encoding.Binary.to_bytes_exn protocol_data_encoding protocol_data; + } diff --git a/src/proto_009_PsFLoren/lib_protocol/block_header_repr.mli b/src/proto_009_PsFLoren/lib_protocol/block_header_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..374a0640ea1ea3ea47e8b134baf11c766cfb6172 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/block_header_repr.mli @@ -0,0 +1,61 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type contents = { + priority : int; + seed_nonce_hash : Nonce_hash.t option; + proof_of_work_nonce : bytes; +} + +type protocol_data = {contents : contents; signature : Signature.t} + +type t = {shell : Block_header.shell_header; protocol_data : protocol_data} + +type block_header = t + +type raw = Block_header.t + +type shell_header = Block_header.shell_header + +val raw : block_header -> raw + +val encoding : block_header Data_encoding.encoding + +val raw_encoding : raw Data_encoding.t + +val contents_encoding : contents Data_encoding.t + +val unsigned_encoding : (Block_header.shell_header * contents) Data_encoding.t + +val protocol_data_encoding : protocol_data Data_encoding.encoding + +val shell_header_encoding : shell_header Data_encoding.encoding + +(** The maximum size of block headers in bytes *) +val max_header_length : int + +val hash : block_header -> Block_hash.t + +val hash_raw : raw -> Block_hash.t diff --git a/src/proto_009_PsFLoren/lib_protocol/bootstrap_storage.ml b/src/proto_009_PsFLoren/lib_protocol/bootstrap_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..26b59dfd0200d8312cc8069c651c2786667f5700 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/bootstrap_storage.ml @@ -0,0 +1,147 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Misc + +let init_account ctxt + ({public_key_hash; public_key; amount} : Parameters_repr.bootstrap_account) + = + let contract = Contract_repr.implicit_contract public_key_hash in + Contract_storage.credit ctxt contract amount + >>=? fun ctxt -> + match public_key with + | Some public_key -> + Contract_storage.reveal_manager_key ctxt public_key_hash public_key + >>=? fun ctxt -> + Delegate_storage.set ctxt contract (Some public_key_hash) + | None -> + return ctxt + +let init_contract ~typecheck ctxt + ({delegate; amount; script} : Parameters_repr.bootstrap_contract) = + Contract_storage.fresh_contract_from_current_nonce ctxt + >>?= fun (ctxt, contract) -> + typecheck ctxt script + >>=? fun (script, ctxt) -> + Contract_storage.raw_originate + ctxt + contract + ~balance:amount + ~prepaid_bootstrap_storage:true + ~script + ~delegate:(Some delegate) + +let init ctxt ~typecheck ?ramp_up_cycles ?no_reward_cycles accounts contracts = + let nonce = + Operation_hash.hash_bytes [Bytes.of_string "Un festival de GADT."] + in + let ctxt = Raw_context.init_origination_nonce ctxt nonce in + fold_left_s init_account ctxt accounts + >>=? fun ctxt -> + fold_left_s (init_contract ~typecheck) ctxt contracts + >>=? fun ctxt -> + ( match no_reward_cycles with + | None -> + return ctxt + | Some cycles -> + (* Store pending ramp ups. *) + let constants = Raw_context.constants ctxt in + (* Start without rewards *) + Raw_context.patch_constants ctxt (fun c -> + { + c with + baking_reward_per_endorsement = [Tez_repr.zero]; + endorsement_reward = [Tez_repr.zero]; + }) + >>= fun ctxt -> + (* Store the final reward. *) + Storage.Ramp_up.Rewards.init + ctxt + (Cycle_repr.of_int32_exn (Int32.of_int cycles)) + (constants.baking_reward_per_endorsement, constants.endorsement_reward) + ) + >>=? fun ctxt -> + match ramp_up_cycles with + | None -> + return ctxt + | Some cycles -> + (* Store pending ramp ups. *) + let constants = Raw_context.constants ctxt in + Tez_repr.(constants.block_security_deposit /? Int64.of_int cycles) + >>?= fun block_step -> + Tez_repr.(constants.endorsement_security_deposit /? Int64.of_int cycles) + >>?= fun endorsement_step -> + (* Start without security_deposit *) + Raw_context.patch_constants ctxt (fun c -> + { + c with + block_security_deposit = Tez_repr.zero; + endorsement_security_deposit = Tez_repr.zero; + }) + >>= fun ctxt -> + fold_left_s + (fun ctxt cycle -> + Tez_repr.(block_step *? Int64.of_int cycle) + >>?= fun block_security_deposit -> + Tez_repr.(endorsement_step *? Int64.of_int cycle) + >>?= fun endorsement_security_deposit -> + let cycle = Cycle_repr.of_int32_exn (Int32.of_int cycle) in + Storage.Ramp_up.Security_deposits.init + ctxt + cycle + (block_security_deposit, endorsement_security_deposit)) + ctxt + (1 --> (cycles - 1)) + >>=? fun ctxt -> + (* Store the final security deposits. *) + Storage.Ramp_up.Security_deposits.init + ctxt + (Cycle_repr.of_int32_exn (Int32.of_int cycles)) + ( constants.block_security_deposit, + constants.endorsement_security_deposit ) + +let cycle_end ctxt last_cycle = + let next_cycle = Cycle_repr.succ last_cycle in + Storage.Ramp_up.Rewards.find ctxt next_cycle + >>=? (function + | None -> + return ctxt + | Some (baking_reward_per_endorsement, endorsement_reward) -> + Storage.Ramp_up.Rewards.remove_existing ctxt next_cycle + >>=? fun ctxt -> + Raw_context.patch_constants ctxt (fun c -> + {c with baking_reward_per_endorsement; endorsement_reward}) + >|= ok) + >>=? fun ctxt -> + Storage.Ramp_up.Security_deposits.find ctxt next_cycle + >>=? function + | None -> + return ctxt + | Some (block_security_deposit, endorsement_security_deposit) -> + Storage.Ramp_up.Security_deposits.remove_existing ctxt next_cycle + >>=? fun ctxt -> + Raw_context.patch_constants ctxt (fun c -> + {c with block_security_deposit; endorsement_security_deposit}) + >|= ok diff --git a/src/proto_009_PsFLoren/lib_protocol/bootstrap_storage.mli b/src/proto_009_PsFLoren/lib_protocol/bootstrap_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..0fb7b720b6a53d3118a86dbf6035222fefe606ef --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/bootstrap_storage.mli @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val init : + Raw_context.t -> + typecheck:(Raw_context.t -> + Script_repr.t -> + ((Script_repr.t * Lazy_storage_diff.diffs option) * Raw_context.t) + tzresult + Lwt.t) -> + ?ramp_up_cycles:int -> + ?no_reward_cycles:int -> + Parameters_repr.bootstrap_account list -> + Parameters_repr.bootstrap_contract list -> + Raw_context.t tzresult Lwt.t + +val cycle_end : Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/commitment_repr.ml b/src/proto_009_PsFLoren/lib_protocol/commitment_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..e64be9c0114ecc0a41358ffe9a2974ec9b040014 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/commitment_repr.ml @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + blinded_public_key_hash : Blinded_public_key_hash.t; + amount : Tez_repr.t; +} + +let encoding = + let open Data_encoding in + conv + (fun {blinded_public_key_hash; amount} -> + (blinded_public_key_hash, amount)) + (fun (blinded_public_key_hash, amount) -> + {blinded_public_key_hash; amount}) + (tup2 Blinded_public_key_hash.encoding Tez_repr.encoding) diff --git a/src/proto_009_PsFLoren/lib_protocol/commitment_repr.mli b/src/proto_009_PsFLoren/lib_protocol/commitment_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..edca4134d844a163dfbdf9708af1797acfcfa46a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/commitment_repr.mli @@ -0,0 +1,31 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + blinded_public_key_hash : Blinded_public_key_hash.t; + amount : Tez_repr.t; +} + +val encoding : t Data_encoding.t diff --git a/src/proto_009_PsFLoren/lib_protocol/commitment_storage.ml b/src/proto_009_PsFLoren/lib_protocol/commitment_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..c0e24455de1020cd80a0609e87e6d92ac1e4d70e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/commitment_storage.ml @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let find = Storage.Commitments.find + +let remove_existing = Storage.Commitments.remove_existing + +let init ctxt commitments = + let init_commitment ctxt Commitment_repr.{blinded_public_key_hash; amount} = + Storage.Commitments.init ctxt blinded_public_key_hash amount + in + fold_left_s init_commitment ctxt commitments diff --git a/src/proto_009_PsFLoren/lib_protocol/commitment_storage.mli b/src/proto_009_PsFLoren/lib_protocol/commitment_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..1044b7a5bd70ce42e8516d5ea565675dbb441cc2 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/commitment_storage.mli @@ -0,0 +1,35 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val init : + Raw_context.t -> Commitment_repr.t list -> Raw_context.t tzresult Lwt.t + +val find : + Raw_context.t -> + Blinded_public_key_hash.t -> + Tez_repr.t option tzresult Lwt.t + +val remove_existing : + Raw_context.t -> Blinded_public_key_hash.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/constants_repr.ml b/src/proto_009_PsFLoren/lib_protocol/constants_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..fcb98b5de6851214d22ed3f19038ed032ae6f793 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/constants_repr.ml @@ -0,0 +1,244 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let version_number_004 = "\000" + +let version_number = "\001" + +let proof_of_work_nonce_size = 8 + +let nonce_length = 32 + +let max_anon_ops_per_block = 132 + +let max_proposals_per_delegate = 20 + +let max_operation_data_length = 32 * 1024 (* 32kB *) + +type fixed = { + proof_of_work_nonce_size : int; + nonce_length : int; + max_anon_ops_per_block : int; + max_operation_data_length : int; + max_proposals_per_delegate : int; +} + +let fixed_encoding = + let open Data_encoding in + conv + (fun c -> + ( c.proof_of_work_nonce_size, + c.nonce_length, + c.max_anon_ops_per_block, + c.max_operation_data_length, + c.max_proposals_per_delegate )) + (fun ( proof_of_work_nonce_size, + nonce_length, + max_anon_ops_per_block, + max_operation_data_length, + max_proposals_per_delegate ) -> + { + proof_of_work_nonce_size; + nonce_length; + max_anon_ops_per_block; + max_operation_data_length; + max_proposals_per_delegate; + }) + (obj5 + (req "proof_of_work_nonce_size" uint8) + (req "nonce_length" uint8) + (req "max_anon_ops_per_block" uint8) + (req "max_operation_data_length" int31) + (req "max_proposals_per_delegate" uint8)) + +let fixed = + { + proof_of_work_nonce_size; + nonce_length; + max_anon_ops_per_block; + max_operation_data_length; + max_proposals_per_delegate; + } + +type parametric = { + preserved_cycles : int; + blocks_per_cycle : int32; + blocks_per_commitment : int32; + blocks_per_roll_snapshot : int32; + blocks_per_voting_period : int32; + time_between_blocks : Period_repr.t list; + endorsers_per_block : int; + hard_gas_limit_per_operation : Gas_limit_repr.Arith.integral; + hard_gas_limit_per_block : Gas_limit_repr.Arith.integral; + proof_of_work_threshold : int64; + tokens_per_roll : Tez_repr.t; + michelson_maximum_type_size : int; + seed_nonce_revelation_tip : Tez_repr.t; + origination_size : int; + block_security_deposit : Tez_repr.t; + endorsement_security_deposit : Tez_repr.t; + baking_reward_per_endorsement : Tez_repr.t list; + endorsement_reward : Tez_repr.t list; + cost_per_byte : Tez_repr.t; + hard_storage_limit_per_operation : Z.t; + quorum_min : int32; + quorum_max : int32; + min_proposal_quorum : int32; + initial_endorsers : int; + delay_per_missing_endorsement : Period_repr.t; +} + +let parametric_encoding = + let open Data_encoding in + conv + (fun c -> + ( ( c.preserved_cycles, + c.blocks_per_cycle, + c.blocks_per_commitment, + c.blocks_per_roll_snapshot, + c.blocks_per_voting_period, + c.time_between_blocks, + c.endorsers_per_block, + c.hard_gas_limit_per_operation, + c.hard_gas_limit_per_block ), + ( ( c.proof_of_work_threshold, + c.tokens_per_roll, + c.michelson_maximum_type_size, + c.seed_nonce_revelation_tip, + c.origination_size, + c.block_security_deposit, + c.endorsement_security_deposit, + c.baking_reward_per_endorsement ), + ( c.endorsement_reward, + c.cost_per_byte, + c.hard_storage_limit_per_operation, + 0L, + (* At this position in the encoding we used to have a test + chain duration but it is not used anymore and should be + removed when this encoding is updated. When the test + chain was removed, we did not want to change the + encoding for retrocompatibility. *) + c.quorum_min, + c.quorum_max, + c.min_proposal_quorum, + c.initial_endorsers, + c.delay_per_missing_endorsement ) ) )) + (fun ( ( preserved_cycles, + blocks_per_cycle, + blocks_per_commitment, + blocks_per_roll_snapshot, + blocks_per_voting_period, + time_between_blocks, + endorsers_per_block, + hard_gas_limit_per_operation, + hard_gas_limit_per_block ), + ( ( proof_of_work_threshold, + tokens_per_roll, + michelson_maximum_type_size, + seed_nonce_revelation_tip, + origination_size, + block_security_deposit, + endorsement_security_deposit, + baking_reward_per_endorsement ), + ( endorsement_reward, + cost_per_byte, + hard_storage_limit_per_operation, + _test_chain_duration, + quorum_min, + quorum_max, + min_proposal_quorum, + initial_endorsers, + delay_per_missing_endorsement ) ) ) -> + { + preserved_cycles; + blocks_per_cycle; + blocks_per_commitment; + blocks_per_roll_snapshot; + blocks_per_voting_period; + time_between_blocks; + endorsers_per_block; + hard_gas_limit_per_operation; + hard_gas_limit_per_block; + proof_of_work_threshold; + tokens_per_roll; + michelson_maximum_type_size; + seed_nonce_revelation_tip; + origination_size; + block_security_deposit; + endorsement_security_deposit; + baking_reward_per_endorsement; + endorsement_reward; + cost_per_byte; + hard_storage_limit_per_operation; + quorum_min; + quorum_max; + min_proposal_quorum; + initial_endorsers; + delay_per_missing_endorsement; + }) + (merge_objs + (obj9 + (req "preserved_cycles" uint8) + (req "blocks_per_cycle" int32) + (req "blocks_per_commitment" int32) + (req "blocks_per_roll_snapshot" int32) + (req "blocks_per_voting_period" int32) + (req "time_between_blocks" (list Period_repr.encoding)) + (req "endorsers_per_block" uint16) + (req + "hard_gas_limit_per_operation" + Gas_limit_repr.Arith.z_integral_encoding) + (req + "hard_gas_limit_per_block" + Gas_limit_repr.Arith.z_integral_encoding)) + (merge_objs + (obj8 + (req "proof_of_work_threshold" int64) + (req "tokens_per_roll" Tez_repr.encoding) + (req "michelson_maximum_type_size" uint16) + (req "seed_nonce_revelation_tip" Tez_repr.encoding) + (req "origination_size" int31) + (req "block_security_deposit" Tez_repr.encoding) + (req "endorsement_security_deposit" Tez_repr.encoding) + (req "baking_reward_per_endorsement" (list Tez_repr.encoding))) + (obj9 + (req "endorsement_reward" (list Tez_repr.encoding)) + (req "cost_per_byte" Tez_repr.encoding) + (req "hard_storage_limit_per_operation" z) + (req "test_chain_duration" int64) + (req "quorum_min" int32) + (req "quorum_max" int32) + (req "min_proposal_quorum" int32) + (req "initial_endorsers" uint16) + (req "delay_per_missing_endorsement" Period_repr.encoding)))) + +type t = {fixed : fixed; parametric : parametric} + +let encoding = + let open Data_encoding in + conv + (fun {fixed; parametric} -> (fixed, parametric)) + (fun (fixed, parametric) -> {fixed; parametric}) + (merge_objs fixed_encoding parametric_encoding) diff --git a/src/proto_009_PsFLoren/lib_protocol/constants_repr.mli b/src/proto_009_PsFLoren/lib_protocol/constants_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..3d560ee1ba7afc0912706fe9c324a4c31db7e36c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/constants_repr.mli @@ -0,0 +1,86 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val version_number_004 : string + +val version_number : string + +val proof_of_work_nonce_size : int + +val nonce_length : int + +val max_anon_ops_per_block : int + +val max_proposals_per_delegate : int + +val max_operation_data_length : int + +type fixed = { + proof_of_work_nonce_size : int; + nonce_length : int; + max_anon_ops_per_block : int; + max_operation_data_length : int; + max_proposals_per_delegate : int; +} + +val fixed_encoding : fixed Data_encoding.encoding + +val fixed : fixed + +type parametric = { + preserved_cycles : int; + blocks_per_cycle : int32; + blocks_per_commitment : int32; + blocks_per_roll_snapshot : int32; + blocks_per_voting_period : int32; + time_between_blocks : Period_repr.t list; + endorsers_per_block : int; + hard_gas_limit_per_operation : Gas_limit_repr.Arith.integral; + hard_gas_limit_per_block : Gas_limit_repr.Arith.integral; + proof_of_work_threshold : int64; + tokens_per_roll : Tez_repr.t; + michelson_maximum_type_size : int; + seed_nonce_revelation_tip : Tez_repr.t; + origination_size : int; + block_security_deposit : Tez_repr.t; + endorsement_security_deposit : Tez_repr.t; + baking_reward_per_endorsement : Tez_repr.t list; + endorsement_reward : Tez_repr.t list; + cost_per_byte : Tez_repr.t; + hard_storage_limit_per_operation : Z.t; + (* in seconds *) + quorum_min : int32; + quorum_max : int32; + min_proposal_quorum : int32; + initial_endorsers : int; + delay_per_missing_endorsement : Period_repr.t; +} + +val parametric_encoding : parametric Data_encoding.encoding + +type t = {fixed : fixed; parametric : parametric} + +val encoding : t Data_encoding.encoding diff --git a/src/proto_009_PsFLoren/lib_protocol/constants_services.ml b/src/proto_009_PsFLoren/lib_protocol/constants_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..f2b92f91c18d3c1de6f40df91b1856caaccbae78 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/constants_services.ml @@ -0,0 +1,60 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let custom_root = + ( RPC_path.(open_root / "context" / "constants") + : RPC_context.t RPC_path.context ) + +module S = struct + open Data_encoding + + let errors = + RPC_service.get_service + ~description:"Schema for all the RPC errors from this protocol version" + ~query:RPC_query.empty + ~output:json_schema + RPC_path.(custom_root / "errors") + + let all = + RPC_service.get_service + ~description:"All constants" + ~query:RPC_query.empty + ~output:Alpha_context.Constants.encoding + custom_root +end + +let register () = + let open Services_registration in + register0_noctxt S.errors (fun () () -> + return Data_encoding.Json.(schema error_encoding)) ; + register0 S.all (fun ctxt () () -> + let open Constants in + return {fixed; parametric = parametric ctxt}) + +let errors ctxt block = RPC_context.make_call0 S.errors ctxt block () () + +let all ctxt block = RPC_context.make_call0 S.all ctxt block () () diff --git a/src/proto_009_PsFLoren/lib_protocol/constants_services.mli b/src/proto_009_PsFLoren/lib_protocol/constants_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..243adcb1d384affd169f19ce3a897f19daac8ce8 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/constants_services.mli @@ -0,0 +1,36 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +val errors : + 'a #RPC_context.simple -> + 'a -> + Data_encoding.json_schema shell_tzresult Lwt.t + +(** Returns all the constants of the protocol *) +val all : 'a #RPC_context.simple -> 'a -> Constants.t shell_tzresult Lwt.t + +val register : unit -> unit diff --git a/src/proto_009_PsFLoren/lib_protocol/constants_storage.ml b/src/proto_009_PsFLoren/lib_protocol/constants_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..772b11e875bc2ddda890b995375926f97da42e59 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/constants_storage.ml @@ -0,0 +1,126 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let preserved_cycles c = + let constants = Raw_context.constants c in + constants.preserved_cycles + +let blocks_per_cycle c = + let constants = Raw_context.constants c in + constants.blocks_per_cycle + +let blocks_per_commitment c = + let constants = Raw_context.constants c in + constants.blocks_per_commitment + +let blocks_per_roll_snapshot c = + let constants = Raw_context.constants c in + constants.blocks_per_roll_snapshot + +let blocks_per_voting_period c = + let constants = Raw_context.constants c in + constants.blocks_per_voting_period + +let time_between_blocks c = + let constants = Raw_context.constants c in + constants.time_between_blocks + +let endorsers_per_block c = + let constants = Raw_context.constants c in + constants.endorsers_per_block + +let initial_endorsers c = + let constants = Raw_context.constants c in + constants.initial_endorsers + +let delay_per_missing_endorsement c = + let constants = Raw_context.constants c in + constants.delay_per_missing_endorsement + +let hard_gas_limit_per_operation c = + let constants = Raw_context.constants c in + constants.hard_gas_limit_per_operation + +let hard_gas_limit_per_block c = + let constants = Raw_context.constants c in + constants.hard_gas_limit_per_block + +let cost_per_byte c = + let constants = Raw_context.constants c in + constants.cost_per_byte + +let hard_storage_limit_per_operation c = + let constants = Raw_context.constants c in + constants.hard_storage_limit_per_operation + +let proof_of_work_threshold c = + let constants = Raw_context.constants c in + constants.proof_of_work_threshold + +let tokens_per_roll c = + let constants = Raw_context.constants c in + constants.tokens_per_roll + +let michelson_maximum_type_size c = + let constants = Raw_context.constants c in + constants.michelson_maximum_type_size + +let seed_nonce_revelation_tip c = + let constants = Raw_context.constants c in + constants.seed_nonce_revelation_tip + +let origination_size c = + let constants = Raw_context.constants c in + constants.origination_size + +let block_security_deposit c = + let constants = Raw_context.constants c in + constants.block_security_deposit + +let endorsement_security_deposit c = + let constants = Raw_context.constants c in + constants.endorsement_security_deposit + +let baking_reward_per_endorsement c = + let constants = Raw_context.constants c in + constants.baking_reward_per_endorsement + +let endorsement_reward c = + let constants = Raw_context.constants c in + constants.endorsement_reward + +let quorum_min c = + let constants = Raw_context.constants c in + constants.quorum_min + +let quorum_max c = + let constants = Raw_context.constants c in + constants.quorum_max + +let min_proposal_quorum c = + let constants = Raw_context.constants c in + constants.min_proposal_quorum + +let parametric c = Raw_context.constants c diff --git a/src/proto_009_PsFLoren/lib_protocol/constants_storage.mli b/src/proto_009_PsFLoren/lib_protocol/constants_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..34fa2f6228b1bdad0a2dca6b8030321de072087e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/constants_storage.mli @@ -0,0 +1,78 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val preserved_cycles : Raw_context.t -> int + +val blocks_per_cycle : Raw_context.t -> int32 + +val blocks_per_commitment : Raw_context.t -> int32 + +val blocks_per_roll_snapshot : Raw_context.t -> int32 + +val blocks_per_voting_period : Raw_context.t -> int32 + +val time_between_blocks : Raw_context.t -> Period_repr.t list + +val endorsers_per_block : Raw_context.t -> int + +val initial_endorsers : Raw_context.t -> int + +val delay_per_missing_endorsement : Raw_context.t -> Period_repr.t + +val hard_gas_limit_per_operation : + Raw_context.t -> Gas_limit_repr.Arith.integral + +val hard_gas_limit_per_block : Raw_context.t -> Gas_limit_repr.Arith.integral + +val cost_per_byte : Raw_context.t -> Tez_repr.t + +val hard_storage_limit_per_operation : Raw_context.t -> Z.t + +val proof_of_work_threshold : Raw_context.t -> int64 + +val tokens_per_roll : Raw_context.t -> Tez_repr.t + +val michelson_maximum_type_size : Raw_context.t -> int + +val seed_nonce_revelation_tip : Raw_context.t -> Tez_repr.t + +val origination_size : Raw_context.t -> int + +val block_security_deposit : Raw_context.t -> Tez_repr.t + +val endorsement_security_deposit : Raw_context.t -> Tez_repr.t + +val baking_reward_per_endorsement : Raw_context.t -> Tez_repr.t list + +val endorsement_reward : Raw_context.t -> Tez_repr.t list + +val quorum_min : Raw_context.t -> int32 + +val quorum_max : Raw_context.t -> int32 + +val min_proposal_quorum : Raw_context.t -> int32 + +val parametric : Raw_context.t -> Constants_repr.parametric diff --git a/src/proto_009_PsFLoren/lib_protocol/contract_hash.ml b/src/proto_009_PsFLoren/lib_protocol/contract_hash.ml new file mode 100644 index 0000000000000000000000000000000000000000..40d94808d628f0f52fc9a83a4f77a566b841fc0f --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/contract_hash.ml @@ -0,0 +1,41 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* 20 *) +let contract_hash = "\002\090\121" (* KT1(36) *) + +include Blake2B.Make + (Base58) + (struct + let name = "Contract_hash" + + let title = "A contract ID" + + let b58check_prefix = contract_hash + + let size = Some 20 + end) + +let () = Base58.check_encoded_prefix b58check_encoding "KT1" 36 diff --git a/src/proto_009_PsFLoren/lib_protocol/contract_hash.mli b/src/proto_009_PsFLoren/lib_protocol/contract_hash.mli new file mode 100644 index 0000000000000000000000000000000000000000..5e374f2a38c0b0f7da05eaa33e91932d40e49838 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/contract_hash.mli @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include S.HASH diff --git a/src/proto_009_PsFLoren/lib_protocol/contract_repr.ml b/src/proto_009_PsFLoren/lib_protocol/contract_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..1fd9d0c5d43ccceab5c24cb927979eff35435dbb --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/contract_repr.ml @@ -0,0 +1,230 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = + | Implicit of Signature.Public_key_hash.t + | Originated of Contract_hash.t + +include Compare.Make (struct + type nonrec t = t + + let compare l1 l2 = + match (l1, l2) with + | (Implicit pkh1, Implicit pkh2) -> + Signature.Public_key_hash.compare pkh1 pkh2 + | (Originated h1, Originated h2) -> + Contract_hash.compare h1 h2 + | (Implicit _, Originated _) -> + -1 + | (Originated _, Implicit _) -> + 1 +end) + +type contract = t + +type error += Invalid_contract_notation of string (* `Permanent *) + +let to_b58check = function + | Implicit pbk -> + Signature.Public_key_hash.to_b58check pbk + | Originated h -> + Contract_hash.to_b58check h + +let of_b58check s = + match Base58.decode s with + | Some (Ed25519.Public_key_hash.Data h) -> + ok (Implicit (Signature.Ed25519 h)) + | Some (Secp256k1.Public_key_hash.Data h) -> + ok (Implicit (Signature.Secp256k1 h)) + | Some (P256.Public_key_hash.Data h) -> + ok (Implicit (Signature.P256 h)) + | Some (Contract_hash.Data h) -> + ok (Originated h) + | _ -> + error (Invalid_contract_notation s) + +let pp ppf = function + | Implicit pbk -> + Signature.Public_key_hash.pp ppf pbk + | Originated h -> + Contract_hash.pp ppf h + +let pp_short ppf = function + | Implicit pbk -> + Signature.Public_key_hash.pp_short ppf pbk + | Originated h -> + Contract_hash.pp_short ppf h + +let encoding = + let open Data_encoding in + def + "contract_id" + ~title:"A contract handle" + ~description: + "A contract notation as given to an RPC or inside scripts. Can be a \ + base58 implicit contract hash or a base58 originated contract hash." + @@ splitted + ~binary: + (union + ~tag_size:`Uint8 + [ case + (Tag 0) + ~title:"Implicit" + Signature.Public_key_hash.encoding + (function Implicit k -> Some k | _ -> None) + (fun k -> Implicit k); + case + (Tag 1) + (Fixed.add_padding Contract_hash.encoding 1) + ~title:"Originated" + (function Originated k -> Some k | _ -> None) + (fun k -> Originated k) ]) + ~json: + (conv + to_b58check + (fun s -> + match of_b58check s with + | Ok s -> + s + | Error _ -> + Json.cannot_destruct "Invalid contract notation.") + string) + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"contract.invalid_contract_notation" + ~title:"Invalid contract notation" + ~pp:(fun ppf x -> Format.fprintf ppf "Invalid contract notation %S" x) + ~description: + "A malformed contract notation was given to an RPC or in a script." + (obj1 (req "notation" string)) + (function Invalid_contract_notation loc -> Some loc | _ -> None) + (fun loc -> Invalid_contract_notation loc) + +let implicit_contract id = Implicit id + +let is_implicit = function Implicit m -> Some m | Originated _ -> None + +let is_originated = function Implicit _ -> None | Originated h -> Some h + +type origination_nonce = { + operation_hash : Operation_hash.t; + origination_index : int32; +} + +let origination_nonce_encoding = + let open Data_encoding in + conv + (fun {operation_hash; origination_index} -> + (operation_hash, origination_index)) + (fun (operation_hash, origination_index) -> + {operation_hash; origination_index}) + @@ obj2 (req "operation" Operation_hash.encoding) (dft "index" int32 0l) + +let originated_contract nonce = + let data = + Data_encoding.Binary.to_bytes_exn origination_nonce_encoding nonce + in + Originated (Contract_hash.hash_bytes [data]) + +let originated_contracts + ~since:{origination_index = first; operation_hash = first_hash} + ~until:( {origination_index = last; operation_hash = last_hash} as + origination_nonce ) = + assert (Operation_hash.equal first_hash last_hash) ; + let rec contracts acc origination_index = + if Compare.Int32.(origination_index < first) then acc + else + let origination_nonce = {origination_nonce with origination_index} in + let acc = originated_contract origination_nonce :: acc in + contracts acc (Int32.pred origination_index) + in + contracts [] (Int32.pred last) + +let initial_origination_nonce operation_hash = + {operation_hash; origination_index = 0l} + +let incr_origination_nonce nonce = + let origination_index = Int32.succ nonce.origination_index in + {nonce with origination_index} + +let rpc_arg = + let construct = to_b58check in + let destruct hash = + match of_b58check hash with + | Error _ -> + Error "Cannot parse contract id" + | Ok contract -> + Ok contract + in + RPC_arg.make + ~descr:"A contract identifier encoded in b58check." + ~name:"contract_id" + ~construct + ~destruct + () + +module Index = struct + type t = contract + + let path_length = 7 + + let to_path c l = + let raw_key = Data_encoding.Binary.to_bytes_exn encoding c in + let (`Hex key) = Hex.of_bytes raw_key in + let (`Hex index_key) = Hex.of_bytes (Raw_hashes.blake2b raw_key) in + String.sub index_key 0 2 :: String.sub index_key 2 2 + :: String.sub index_key 4 2 :: String.sub index_key 6 2 + :: String.sub index_key 8 2 :: String.sub index_key 10 2 :: key :: l + + let of_path = function + | [] + | [_] + | [_; _] + | [_; _; _] + | [_; _; _; _] + | [_; _; _; _; _] + | [_; _; _; _; _; _] + | _ :: _ :: _ :: _ :: _ :: _ :: _ :: _ :: _ -> + None + | [index1; index2; index3; index4; index5; index6; key] -> + let raw_key = Hex.to_bytes (`Hex key) in + let (`Hex index_key) = Hex.of_bytes (Raw_hashes.blake2b raw_key) in + assert (Compare.String.(String.sub index_key 0 2 = index1)) ; + assert (Compare.String.(String.sub index_key 2 2 = index2)) ; + assert (Compare.String.(String.sub index_key 4 2 = index3)) ; + assert (Compare.String.(String.sub index_key 6 2 = index4)) ; + assert (Compare.String.(String.sub index_key 8 2 = index5)) ; + assert (Compare.String.(String.sub index_key 10 2 = index6)) ; + Data_encoding.Binary.of_bytes encoding raw_key + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_009_PsFLoren/lib_protocol/contract_repr.mli b/src/proto_009_PsFLoren/lib_protocol/contract_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..53935e460bbb6e57453a45d5b8593319c4d4de0c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/contract_repr.mli @@ -0,0 +1,80 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = private + | Implicit of Signature.Public_key_hash.t + | Originated of Contract_hash.t + +type contract = t + +include Compare.S with type t := contract + +(** {2 Implicit contracts} *) + +val implicit_contract : Signature.Public_key_hash.t -> contract + +val is_implicit : contract -> Signature.Public_key_hash.t option + +(** {2 Originated contracts} *) + +(** Originated contracts handles are crafted from the hash of the + operation that triggered their origination (and nothing else). + As a single operation can trigger several originations, the + corresponding handles are forged from a deterministic sequence of + nonces, initialized with the hash of the operation. *) +type origination_nonce + +val originated_contract : origination_nonce -> contract + +val originated_contracts : + since:origination_nonce -> until:origination_nonce -> contract list + +val initial_origination_nonce : Operation_hash.t -> origination_nonce + +val incr_origination_nonce : origination_nonce -> origination_nonce + +val is_originated : contract -> Contract_hash.t option + +(** {2 Human readable notation} *) + +type error += Invalid_contract_notation of string (* `Permanent *) + +val to_b58check : contract -> string + +val of_b58check : string -> contract tzresult + +val pp : Format.formatter -> contract -> unit + +val pp_short : Format.formatter -> contract -> unit + +(** {2 Serializers} *) + +val encoding : contract Data_encoding.t + +val origination_nonce_encoding : origination_nonce Data_encoding.t + +val rpc_arg : contract RPC_arg.arg + +module Index : Storage_description.INDEX with type t = t diff --git a/src/proto_009_PsFLoren/lib_protocol/contract_services.ml b/src/proto_009_PsFLoren/lib_protocol/contract_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..ff47b435be859cc66584503a43ba2c2f57eb4109 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/contract_services.ml @@ -0,0 +1,462 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let custom_root = + ( RPC_path.(open_root / "context" / "contracts") + : RPC_context.t RPC_path.context ) + +let big_map_root = + ( RPC_path.(open_root / "context" / "big_maps") + : RPC_context.t RPC_path.context ) + +type info = { + balance : Tez.t; + delegate : public_key_hash option; + counter : counter option; + script : Script.t option; +} + +let info_encoding = + let open Data_encoding in + conv + (fun {balance; delegate; script; counter} -> + (balance, delegate, script, counter)) + (fun (balance, delegate, script, counter) -> + {balance; delegate; script; counter}) + @@ obj4 + (req "balance" Tez.encoding) + (opt "delegate" Signature.Public_key_hash.encoding) + (opt "script" Script.encoding) + (opt "counter" n) + +module S = struct + open Data_encoding + + let balance = + RPC_service.get_service + ~description:"Access the balance of a contract." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "balance") + + let manager_key = + RPC_service.get_service + ~description:"Access the manager of a contract." + ~query:RPC_query.empty + ~output:(option Signature.Public_key.encoding) + RPC_path.(custom_root /: Contract.rpc_arg / "manager_key") + + let delegate = + RPC_service.get_service + ~description:"Access the delegate of a contract, if any." + ~query:RPC_query.empty + ~output:Signature.Public_key_hash.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "delegate") + + let counter = + RPC_service.get_service + ~description:"Access the counter of a contract, if any." + ~query:RPC_query.empty + ~output:z + RPC_path.(custom_root /: Contract.rpc_arg / "counter") + + let script = + RPC_service.get_service + ~description:"Access the code and data of the contract." + ~query:RPC_query.empty + ~output:Script.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "script") + + let storage = + RPC_service.get_service + ~description:"Access the data of the contract." + ~query:RPC_query.empty + ~output:Script.expr_encoding + RPC_path.(custom_root /: Contract.rpc_arg / "storage") + + let entrypoint_type = + RPC_service.get_service + ~description:"Return the type of the given entrypoint of the contract" + ~query:RPC_query.empty + ~output:Script.expr_encoding + RPC_path.( + custom_root /: Contract.rpc_arg / "entrypoints" /: RPC_arg.string) + + let list_entrypoints = + RPC_service.get_service + ~description:"Return the list of entrypoints of the contract" + ~query:RPC_query.empty + ~output: + (obj2 + (dft + "unreachable" + (Data_encoding.list + (obj1 + (req + "path" + (Data_encoding.list + Michelson_v1_primitives.prim_encoding)))) + []) + (req "entrypoints" (assoc Script.expr_encoding))) + RPC_path.(custom_root /: Contract.rpc_arg / "entrypoints") + + let contract_big_map_get_opt = + RPC_service.post_service + ~description: + "Access the value associated with a key in a big map of the contract \ + (deprecated)." + ~query:RPC_query.empty + ~input: + (obj2 + (req "key" Script.expr_encoding) + (req "type" Script.expr_encoding)) + ~output:(option Script.expr_encoding) + RPC_path.(custom_root /: Contract.rpc_arg / "big_map_get") + + let big_map_get = + RPC_service.get_service + ~description:"Access the value associated with a key in a big map." + ~query:RPC_query.empty + ~output:Script.expr_encoding + RPC_path.(big_map_root /: Big_map.Id.rpc_arg /: Script_expr_hash.rpc_arg) + + let info = + RPC_service.get_service + ~description:"Access the complete status of a contract." + ~query:RPC_query.empty + ~output:info_encoding + RPC_path.(custom_root /: Contract.rpc_arg) + + let list = + RPC_service.get_service + ~description: + "All existing contracts (including non-empty default contracts)." + ~query:RPC_query.empty + ~output:(list Contract.encoding) + custom_root + + module Sapling = struct + (* + Sapling: these RPCs are like Sapling RPCs (sapling_services.ml) + specialized for contracts containing a single sapling state. + *) + + let single_sapling_get_id ctxt contract_id = + Contract.get_script ctxt contract_id + >>=? fun (ctxt, script) -> + match script with + | None -> + raise Not_found + | Some script -> + let ctxt = Gas.set_unlimited ctxt in + Script_ir_translator.parse_script + ctxt + ~legacy:true + ~allow_forged_in_storage:true + script + >|= fun tzresult -> + tzresult + >>? fun (Ex_script script, ctxt) -> + Script_ir_translator.get_single_sapling_state + ctxt + script.storage_type + script.storage + + let make_service + Sapling_services.S.Args.{name; description; query; output; f} = + let name = "single_sapling_" ^ name in + let path = RPC_path.(custom_root /: Contract.rpc_arg / name) in + let service = RPC_service.get_service ~description ~query ~output path in + ( service, + fun ctxt contract_id q () -> + single_sapling_get_id ctxt contract_id + >>=? fun (sapling_id, ctxt) -> f ctxt sapling_id q ) + + let get_diff = make_service Sapling_services.S.Args.get_diff + + let register () = + let reg (service, f) = Services_registration.register1 service f in + reg get_diff + + let mk_call1 (service, _f) ctxt block id q = + RPC_context.make_call1 service ctxt block id q () + end +end + +let register () = + let open Services_registration in + register0 S.list (fun ctxt () () -> Contract.list ctxt >|= ok) ; + let register_field s f = + register1 s (fun ctxt contract () () -> + Contract.exists ctxt contract + >>=? function true -> f ctxt contract | false -> raise Not_found) + in + let register_opt_field s f = + register_field s (fun ctxt a1 -> + f ctxt a1 >|=? function None -> raise Not_found | Some v -> v) + in + let do_big_map_get ctxt id key = + let open Script_ir_translator in + let ctxt = Gas.set_unlimited ctxt in + Big_map.exists ctxt id + >>=? fun (ctxt, types) -> + match types with + | None -> + raise Not_found + | Some (_, value_type) -> ( + parse_big_map_value_ty ctxt ~legacy:true (Micheline.root value_type) + >>?= fun (Ex_ty value_type, ctxt) -> + Big_map.get_opt ctxt id key + >>=? fun (_ctxt, value) -> + match value with + | None -> + raise Not_found + | Some value -> + parse_data + ctxt + ~legacy:true + ~allow_forged:true + value_type + (Micheline.root value) + >>=? fun (value, ctxt) -> + unparse_data ctxt Readable value_type value + >|=? fun (value, _ctxt) -> Micheline.strip_locations value ) + in + register_field S.balance Contract.get_balance ; + register1 S.manager_key (fun ctxt contract () () -> + match Contract.is_implicit contract with + | None -> + raise Not_found + | Some mgr -> ( + Contract.is_manager_key_revealed ctxt mgr + >>=? function + | false -> + return_none + | true -> + Contract.get_manager_key ctxt mgr >>=? return_some )) ; + register_opt_field S.delegate Delegate.get ; + register1 S.counter (fun ctxt contract () () -> + match Contract.is_implicit contract with + | None -> + raise Not_found + | Some mgr -> + Contract.get_counter ctxt mgr) ; + register_opt_field S.script (fun c v -> + Contract.get_script c v >|=? fun (_, v) -> v) ; + register_opt_field S.storage (fun ctxt contract -> + Contract.get_script ctxt contract + >>=? fun (ctxt, script) -> + match script with + | None -> + return_none + | Some script -> + let ctxt = Gas.set_unlimited ctxt in + let open Script_ir_translator in + parse_script ctxt ~legacy:true ~allow_forged_in_storage:true script + >>=? fun (Ex_script script, ctxt) -> + unparse_script ctxt Readable script + >>=? fun (script, ctxt) -> + Script.force_decode_in_context ctxt script.storage + >>?= fun (storage, _ctxt) -> return_some storage) ; + register2 S.entrypoint_type (fun ctxt v entrypoint () () -> + Contract.get_script_code ctxt v + >>=? fun (_, expr) -> + match expr with + | None -> + raise Not_found + | Some expr -> + let ctxt = Gas.set_unlimited ctxt in + let legacy = true in + let open Script_ir_translator in + Lwt.return + ( Script.force_decode_in_context ctxt expr + >>? fun (expr, _) -> + parse_toplevel ~legacy expr + >>? (fun (arg_type, _, _, root_name) -> + parse_parameter_ty ctxt ~legacy arg_type + >>? fun (Ex_ty arg_type, _) -> + Script_ir_translator.find_entrypoint + ~root_name + arg_type + entrypoint) + |> function + | Ok (_f, Ex_ty ty) -> + unparse_ty ctxt ty + >|? fun (ty_node, _) -> Micheline.strip_locations ty_node + | Error _ -> + raise Not_found )) ; + register1 S.list_entrypoints (fun ctxt v () () -> + Contract.get_script_code ctxt v + >>=? fun (_, expr) -> + match expr with + | None -> + raise Not_found + | Some expr -> + let ctxt = Gas.set_unlimited ctxt in + let legacy = true in + let open Script_ir_translator in + Lwt.return + ( Script.force_decode_in_context ctxt expr + >>? fun (expr, _) -> + parse_toplevel ~legacy expr + >>? (fun (arg_type, _, _, root_name) -> + parse_parameter_ty ctxt ~legacy arg_type + >>? fun (Ex_ty arg_type, _) -> + Script_ir_translator.list_entrypoints + ~root_name + arg_type + ctxt) + >|? fun (unreachable_entrypoint, map) -> + ( unreachable_entrypoint, + Entrypoints_map.fold + (fun entry (_, ty) acc -> + (entry, Micheline.strip_locations ty) :: acc) + map + [] ) )) ; + register1 S.contract_big_map_get_opt (fun ctxt contract () (key, key_type) -> + Contract.get_script ctxt contract + >>=? fun (ctxt, script) -> + Script_ir_translator.parse_comparable_ty ctxt (Micheline.root key_type) + >>?= fun (Ex_comparable_ty key_type, ctxt) -> + Script_ir_translator.parse_comparable_data + ctxt + key_type + (Micheline.root key) + >>=? fun (key, ctxt) -> + Script_ir_translator.hash_comparable_data ctxt key_type key + >>=? fun (key, ctxt) -> + match script with + | None -> + raise Not_found + | Some script -> ( + let ctxt = Gas.set_unlimited ctxt in + let open Script_ir_translator in + parse_script ctxt ~legacy:true ~allow_forged_in_storage:true script + >>=? fun (Ex_script script, ctxt) -> + Script_ir_translator.collect_lazy_storage + ctxt + script.storage_type + script.storage + >>?= fun (ids, _ctxt) -> + match Script_ir_translator.list_of_big_map_ids ids with + | [] | _ :: _ :: _ -> + return_none + | [id] -> ( + try do_big_map_get ctxt id key >>=? return_some + with Not_found -> return_none ) )) ; + register2 S.big_map_get (fun ctxt id key () () -> do_big_map_get ctxt id key) ; + register_field S.info (fun ctxt contract -> + Contract.get_balance ctxt contract + >>=? fun balance -> + Delegate.get ctxt contract + >>=? fun delegate -> + ( match Contract.is_implicit contract with + | Some manager -> + Contract.get_counter ctxt manager + >>=? fun counter -> return_some counter + | None -> + return_none ) + >>=? fun counter -> + Contract.get_script ctxt contract + >>=? fun (ctxt, script) -> + ( match script with + | None -> + return (None, ctxt) + | Some script -> + let ctxt = Gas.set_unlimited ctxt in + let open Script_ir_translator in + parse_script ctxt ~legacy:true ~allow_forged_in_storage:true script + >>=? fun (Ex_script script, ctxt) -> + unparse_script ctxt Readable script + >|=? fun (script, ctxt) -> (Some script, ctxt) ) + >|=? fun (script, _ctxt) -> {balance; delegate; script; counter}) ; + S.Sapling.register () + +let list ctxt block = RPC_context.make_call0 S.list ctxt block () () + +let info ctxt block contract = + RPC_context.make_call1 S.info ctxt block contract () () + +let balance ctxt block contract = + RPC_context.make_call1 S.balance ctxt block contract () () + +let manager_key ctxt block mgr = + RPC_context.make_call1 + S.manager_key + ctxt + block + (Contract.implicit_contract mgr) + () + () + +let delegate ctxt block contract = + RPC_context.make_call1 S.delegate ctxt block contract () () + +let delegate_opt ctxt block contract = + RPC_context.make_opt_call1 S.delegate ctxt block contract () () + +let counter ctxt block mgr = + RPC_context.make_call1 + S.counter + ctxt + block + (Contract.implicit_contract mgr) + () + () + +let script ctxt block contract = + RPC_context.make_call1 S.script ctxt block contract () () + +let script_opt ctxt block contract = + RPC_context.make_opt_call1 S.script ctxt block contract () () + +let storage ctxt block contract = + RPC_context.make_call1 S.storage ctxt block contract () () + +let entrypoint_type ctxt block contract entrypoint = + RPC_context.make_call2 S.entrypoint_type ctxt block contract entrypoint () () + +let list_entrypoints ctxt block contract = + RPC_context.make_call1 S.list_entrypoints ctxt block contract () () + +let storage_opt ctxt block contract = + RPC_context.make_opt_call1 S.storage ctxt block contract () () + +let big_map_get ctxt block id key = + RPC_context.make_call2 S.big_map_get ctxt block id key () () + +let contract_big_map_get_opt ctxt block contract key = + RPC_context.make_call1 S.contract_big_map_get_opt ctxt block contract () key + +let single_sapling_get_diff ctxt block id ?offset_commitment ?offset_nullifier + () = + S.Sapling.(mk_call1 get_diff) + ctxt + block + id + Sapling_services.{offset_commitment; offset_nullifier} diff --git a/src/proto_009_PsFLoren/lib_protocol/contract_services.mli b/src/proto_009_PsFLoren/lib_protocol/contract_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..db0285932a50a513644ace241390265a644a8f1d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/contract_services.mli @@ -0,0 +1,129 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +val list : 'a #RPC_context.simple -> 'a -> Contract.t list shell_tzresult Lwt.t + +type info = { + balance : Tez.t; + delegate : public_key_hash option; + counter : counter option; + script : Script.t option; +} + +val info_encoding : info Data_encoding.t + +val info : + 'a #RPC_context.simple -> 'a -> Contract.t -> info shell_tzresult Lwt.t + +val balance : + 'a #RPC_context.simple -> 'a -> Contract.t -> Tez.t shell_tzresult Lwt.t + +val manager_key : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + public_key option shell_tzresult Lwt.t + +val delegate : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + public_key_hash shell_tzresult Lwt.t + +val delegate_opt : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + public_key_hash option shell_tzresult Lwt.t + +val counter : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + counter shell_tzresult Lwt.t + +val script : + 'a #RPC_context.simple -> 'a -> Contract.t -> Script.t shell_tzresult Lwt.t + +val script_opt : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + Script.t option shell_tzresult Lwt.t + +val storage : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + Script.expr shell_tzresult Lwt.t + +val entrypoint_type : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + string -> + Script.expr shell_tzresult Lwt.t + +val list_entrypoints : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + (Michelson_v1_primitives.prim list list * (string * Script.expr) list) + shell_tzresult + Lwt.t + +val storage_opt : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + Script.expr option shell_tzresult Lwt.t + +val big_map_get : + 'a #RPC_context.simple -> + 'a -> + Big_map.Id.t -> + Script_expr_hash.t -> + Script.expr shell_tzresult Lwt.t + +val contract_big_map_get_opt : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + Script.expr * Script.expr -> + Script.expr option shell_tzresult Lwt.t + +val single_sapling_get_diff : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + ?offset_commitment:int64 -> + ?offset_nullifier:int64 -> + unit -> + (Sapling.root * Sapling.diff) shell_tzresult Lwt.t + +val register : unit -> unit diff --git a/src/proto_009_PsFLoren/lib_protocol/contract_storage.ml b/src/proto_009_PsFLoren/lib_protocol/contract_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..0de65f45e11ae18019559c0c1d894c669ad263d9 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/contract_storage.ml @@ -0,0 +1,818 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Balance_too_low of Contract_repr.contract * Tez_repr.t * Tez_repr.t + | (* `Temporary *) + Counter_in_the_past of Contract_repr.contract * Z.t * Z.t + | (* `Branch *) + Counter_in_the_future of Contract_repr.contract * Z.t * Z.t + | (* `Temporary *) + Unspendable_contract of Contract_repr.contract + | (* `Permanent *) + Non_existing_contract of Contract_repr.contract + | (* `Temporary *) + Empty_implicit_contract of Signature.Public_key_hash.t + | (* `Temporary *) + Empty_implicit_delegated_contract of + Signature.Public_key_hash.t + | (* `Temporary *) + Empty_transaction of Contract_repr.t (* `Temporary *) + | Inconsistent_hash of + Signature.Public_key.t + * Signature.Public_key_hash.t + * Signature.Public_key_hash.t + | (* `Permanent *) + Inconsistent_public_key of + Signature.Public_key.t * Signature.Public_key.t + | (* `Permanent *) + Failure of string (* `Permanent *) + | Previously_revealed_key of Contract_repr.t (* `Permanent *) + | Unrevealed_manager_key of Contract_repr.t + +(* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"contract.unspendable_contract" + ~title:"Unspendable contract" + ~description: + "An operation tried to spend tokens from an unspendable contract" + ~pp:(fun ppf c -> + Format.fprintf + ppf + "The tokens of contract %a can only be spent by its script" + Contract_repr.pp + c) + Data_encoding.(obj1 (req "contract" Contract_repr.encoding)) + (function Unspendable_contract c -> Some c | _ -> None) + (fun c -> Unspendable_contract c) ; + register_error_kind + `Temporary + ~id:"contract.balance_too_low" + ~title:"Balance too low" + ~description: + "An operation tried to spend more tokens than the contract has" + ~pp:(fun ppf (c, b, a) -> + Format.fprintf + ppf + "Balance of contract %a too low (%a) to spend %a" + Contract_repr.pp + c + Tez_repr.pp + b + Tez_repr.pp + a) + Data_encoding.( + obj3 + (req "contract" Contract_repr.encoding) + (req "balance" Tez_repr.encoding) + (req "amount" Tez_repr.encoding)) + (function Balance_too_low (c, b, a) -> Some (c, b, a) | _ -> None) + (fun (c, b, a) -> Balance_too_low (c, b, a)) ; + register_error_kind + `Temporary + ~id:"contract.counter_in_the_future" + ~title:"Invalid counter (not yet reached) in a manager operation" + ~description:"An operation assumed a contract counter in the future" + ~pp:(fun ppf (contract, exp, found) -> + Format.fprintf + ppf + "Counter %a not yet reached for contract %a (expected %a)" + Z.pp_print + found + Contract_repr.pp + contract + Z.pp_print + exp) + Data_encoding.( + obj3 + (req "contract" Contract_repr.encoding) + (req "expected" z) + (req "found" z)) + (function Counter_in_the_future (c, x, y) -> Some (c, x, y) | _ -> None) + (fun (c, x, y) -> Counter_in_the_future (c, x, y)) ; + register_error_kind + `Branch + ~id:"contract.counter_in_the_past" + ~title:"Invalid counter (already used) in a manager operation" + ~description:"An operation assumed a contract counter in the past" + ~pp:(fun ppf (contract, exp, found) -> + Format.fprintf + ppf + "Counter %a already used for contract %a (expected %a)" + Z.pp_print + found + Contract_repr.pp + contract + Z.pp_print + exp) + Data_encoding.( + obj3 + (req "contract" Contract_repr.encoding) + (req "expected" z) + (req "found" z)) + (function Counter_in_the_past (c, x, y) -> Some (c, x, y) | _ -> None) + (fun (c, x, y) -> Counter_in_the_past (c, x, y)) ; + register_error_kind + `Temporary + ~id:"contract.non_existing_contract" + ~title:"Non existing contract" + ~description: + "A contract handle is not present in the context (either it never was \ + or it has been destroyed)" + ~pp:(fun ppf contract -> + Format.fprintf ppf "Contract %a does not exist" Contract_repr.pp contract) + Data_encoding.(obj1 (req "contract" Contract_repr.encoding)) + (function Non_existing_contract c -> Some c | _ -> None) + (fun c -> Non_existing_contract c) ; + register_error_kind + `Permanent + ~id:"contract.manager.inconsistent_hash" + ~title:"Inconsistent public key hash" + ~description: + "A revealed manager public key is inconsistent with the announced hash" + ~pp:(fun ppf (k, eh, ph) -> + Format.fprintf + ppf + "The hash of the manager public key %s is not %a as announced but %a" + (Signature.Public_key.to_b58check k) + Signature.Public_key_hash.pp + ph + Signature.Public_key_hash.pp + eh) + Data_encoding.( + obj3 + (req "public_key" Signature.Public_key.encoding) + (req "expected_hash" Signature.Public_key_hash.encoding) + (req "provided_hash" Signature.Public_key_hash.encoding)) + (function Inconsistent_hash (k, eh, ph) -> Some (k, eh, ph) | _ -> None) + (fun (k, eh, ph) -> Inconsistent_hash (k, eh, ph)) ; + register_error_kind + `Permanent + ~id:"contract.manager.inconsistent_public_key" + ~title:"Inconsistent public key" + ~description: + "A provided manager public key is different with the public key stored \ + in the contract" + ~pp:(fun ppf (eh, ph) -> + Format.fprintf + ppf + "Expected manager public key %s but %s was provided" + (Signature.Public_key.to_b58check ph) + (Signature.Public_key.to_b58check eh)) + Data_encoding.( + obj2 + (req "public_key" Signature.Public_key.encoding) + (req "expected_public_key" Signature.Public_key.encoding)) + (function Inconsistent_public_key (eh, ph) -> Some (eh, ph) | _ -> None) + (fun (eh, ph) -> Inconsistent_public_key (eh, ph)) ; + register_error_kind + `Permanent + ~id:"contract.failure" + ~title:"Contract storage failure" + ~description:"Unexpected contract storage error" + ~pp:(fun ppf s -> Format.fprintf ppf "Contract_storage.Failure %S" s) + Data_encoding.(obj1 (req "message" string)) + (function Failure s -> Some s | _ -> None) + (fun s -> Failure s) ; + register_error_kind + `Branch + ~id:"contract.unrevealed_key" + ~title:"Manager operation precedes key revelation" + ~description: + "One tried to apply a manager operation without revealing the manager \ + public key" + ~pp:(fun ppf s -> + Format.fprintf + ppf + "Unrevealed manager key for contract %a." + Contract_repr.pp + s) + Data_encoding.(obj1 (req "contract" Contract_repr.encoding)) + (function Unrevealed_manager_key s -> Some s | _ -> None) + (fun s -> Unrevealed_manager_key s) ; + register_error_kind + `Branch + ~id:"contract.previously_revealed_key" + ~title:"Manager operation already revealed" + ~description:"One tried to revealed twice a manager public key" + ~pp:(fun ppf s -> + Format.fprintf + ppf + "Previously revealed manager key for contract %a." + Contract_repr.pp + s) + Data_encoding.(obj1 (req "contract" Contract_repr.encoding)) + (function Previously_revealed_key s -> Some s | _ -> None) + (fun s -> Previously_revealed_key s) ; + register_error_kind + `Branch + ~id:"implicit.empty_implicit_contract" + ~title:"Empty implicit contract" + ~description: + "No manager operations are allowed on an empty implicit contract." + ~pp:(fun ppf implicit -> + Format.fprintf + ppf + "Empty implicit contract (%a)" + Signature.Public_key_hash.pp + implicit) + Data_encoding.(obj1 (req "implicit" Signature.Public_key_hash.encoding)) + (function Empty_implicit_contract c -> Some c | _ -> None) + (fun c -> Empty_implicit_contract c) ; + register_error_kind + `Branch + ~id:"implicit.empty_implicit_delegated_contract" + ~title:"Empty implicit delegated contract" + ~description:"Emptying an implicit delegated account is not allowed." + ~pp:(fun ppf implicit -> + Format.fprintf + ppf + "Emptying implicit delegated contract (%a)" + Signature.Public_key_hash.pp + implicit) + Data_encoding.(obj1 (req "implicit" Signature.Public_key_hash.encoding)) + (function Empty_implicit_delegated_contract c -> Some c | _ -> None) + (fun c -> Empty_implicit_delegated_contract c) ; + register_error_kind + `Branch + ~id:"contract.empty_transaction" + ~title:"Empty transaction" + ~description:"Forbidden to credit 0ꜩ to a contract without code." + ~pp:(fun ppf contract -> + Format.fprintf + ppf + "Transaction of 0ꜩ towards a contract without code are forbidden \ + (%a)." + Contract_repr.pp + contract) + Data_encoding.(obj1 (req "contract" Contract_repr.encoding)) + (function Empty_transaction c -> Some c | _ -> None) + (fun c -> Empty_transaction c) + +let failwith msg = fail (Failure msg) + +module Legacy_big_map_diff = struct + (* + Big_map_diff receipt as it was represented in 006 and earlier. + It is kept here for now for backward compatibility of tools. *) + + type item = + | Update of { + big_map : Z.t; + diff_key : Script_repr.expr; + diff_key_hash : Script_expr_hash.t; + diff_value : Script_repr.expr option; + } + | Clear of Z.t + | Copy of {src : Z.t; dst : Z.t} + | Alloc of { + big_map : Z.t; + key_type : Script_repr.expr; + value_type : Script_repr.expr; + } + + type t = item list + + let item_encoding = + let open Data_encoding in + union + [ case + (Tag 0) + ~title:"update" + (obj5 + (req "action" (constant "update")) + (req "big_map" z) + (req "key_hash" Script_expr_hash.encoding) + (req "key" Script_repr.expr_encoding) + (opt "value" Script_repr.expr_encoding)) + (function + | Update {big_map; diff_key_hash; diff_key; diff_value} -> + Some ((), big_map, diff_key_hash, diff_key, diff_value) + | _ -> + None) + (fun ((), big_map, diff_key_hash, diff_key, diff_value) -> + Update {big_map; diff_key_hash; diff_key; diff_value}); + case + (Tag 1) + ~title:"remove" + (obj2 (req "action" (constant "remove")) (req "big_map" z)) + (function Clear big_map -> Some ((), big_map) | _ -> None) + (fun ((), big_map) -> Clear big_map); + case + (Tag 2) + ~title:"copy" + (obj3 + (req "action" (constant "copy")) + (req "source_big_map" z) + (req "destination_big_map" z)) + (function Copy {src; dst} -> Some ((), src, dst) | _ -> None) + (fun ((), src, dst) -> Copy {src; dst}); + case + (Tag 3) + ~title:"alloc" + (obj4 + (req "action" (constant "alloc")) + (req "big_map" z) + (req "key_type" Script_repr.expr_encoding) + (req "value_type" Script_repr.expr_encoding)) + (function + | Alloc {big_map; key_type; value_type} -> + Some ((), big_map, key_type, value_type) + | _ -> + None) + (fun ((), big_map, key_type, value_type) -> + Alloc {big_map; key_type; value_type}) ] + + let encoding = Data_encoding.list item_encoding + + let to_lazy_storage_diff legacy_diffs = + let rev_head (diffs : (_ * (_, _, _) Lazy_storage_diff.diff) list) = + match diffs with + | [] -> + [] + | (_, Remove) :: _ -> + diffs + | (id, Update {init; updates}) :: rest -> + (id, Update {init; updates = List.rev updates}) :: rest + in + (* Invariant: + Updates are collected one by one, in reverse order, on the head diff + item. So only and exactly the head diff item has its updates reversed. + *) + List.fold_left + (fun (new_diff : (_ * (_, _, _) Lazy_storage_diff.diff) list) item -> + match item with + | Clear id -> + (id, Lazy_storage_diff.Remove) :: rev_head new_diff + | Copy {src; dst} -> + let src = + Lazy_storage_kind.Big_map.Id + .of_legacy_USE_ONLY_IN_Legacy_big_map_diff + src + in + (dst, Lazy_storage_diff.Update {init = Copy {src}; updates = []}) + :: rev_head new_diff + | Alloc {big_map; key_type; value_type} -> + ( big_map, + Lazy_storage_diff.( + Update + { + init = + Alloc Lazy_storage_kind.Big_map.{key_type; value_type}; + updates = []; + }) ) + :: rev_head new_diff + | Update + { big_map; + diff_key = key; + diff_key_hash = key_hash; + diff_value = value } -> ( + match new_diff with + | (id, diff) :: rest when Compare.Z.(id = big_map) -> + let diff = + match diff with + | Remove -> + assert false + | Update {init; updates} -> + let updates = + Lazy_storage_kind.Big_map.{key; key_hash; value} + :: updates + in + Lazy_storage_diff.Update {init; updates} + in + (id, diff) :: rest + | new_diff -> + let updates = + [Lazy_storage_kind.Big_map.{key; key_hash; value}] + in + (big_map, Update {init = Existing; updates}) :: rev_head new_diff + )) + [] + legacy_diffs + |> rev_head + |> List.rev_map (fun (id, diff) -> + let id = + Lazy_storage_kind.Big_map.Id + .of_legacy_USE_ONLY_IN_Legacy_big_map_diff + id + in + Lazy_storage_diff.make Lazy_storage_kind.Big_map id diff) + + let of_lazy_storage_diff diffs = + List.fold_left + (fun legacy_diffs (Lazy_storage_diff.Item (kind, id, diff)) -> + let diffs = + match kind with + | Lazy_storage_kind.Big_map -> ( + let id = + Lazy_storage_kind.Big_map.Id + .to_legacy_USE_ONLY_IN_Legacy_big_map_diff + id + in + match diff with + | Remove -> + [Clear id] + | Update {init; updates} -> ( + let updates = + List.rev_map + (fun {Lazy_storage_kind.Big_map.key; key_hash; value} -> + Update + { + big_map = id; + diff_key = key; + diff_key_hash = key_hash; + diff_value = value; + }) + updates + in + match init with + | Existing -> + updates + | Copy {src} -> + let src = + Lazy_storage_kind.Big_map.Id + .to_legacy_USE_ONLY_IN_Legacy_big_map_diff + src + in + Copy {src; dst = id} :: updates + | Alloc {key_type; value_type} -> + Alloc {big_map = id; key_type; value_type} :: updates ) ) + | _ -> + (* Not a Big_map *) [] + in + diffs :: legacy_diffs) + [] + diffs + |> List.rev |> List.flatten + [@@coq_axiom "gadt"] +end + +let update_script_lazy_storage c = function + | None -> + return (c, Z.zero) + | Some diffs -> + Lazy_storage_diff.apply c diffs + +let create_base c ?(prepaid_bootstrap_storage = false) + (* Free space for bootstrap contracts *) + contract ~balance ~manager ~delegate ?script () = + ( match Contract_repr.is_implicit contract with + | None -> + return c + | Some _ -> + Storage.Contract.Global_counter.get c + >>=? fun counter -> Storage.Contract.Counter.init c contract counter ) + >>=? fun c -> + Storage.Contract.Balance.init c contract balance + >>=? fun c -> + ( match manager with + | Some manager -> + Storage.Contract.Manager.init c contract (Manager_repr.Hash manager) + | None -> + return c ) + >>=? fun c -> + ( match delegate with + | None -> + return c + | Some delegate -> + Delegate_storage.init c contract delegate ) + >>=? fun c -> + match script with + | Some ({Script_repr.code; storage}, lazy_storage_diff) -> + Storage.Contract.Code.init c contract code + >>=? fun (c, code_size) -> + Storage.Contract.Storage.init c contract storage + >>=? fun (c, storage_size) -> + update_script_lazy_storage c lazy_storage_diff + >>=? fun (c, lazy_storage_size) -> + let total_size = + Z.add + (Z.add (Z.of_int code_size) (Z.of_int storage_size)) + lazy_storage_size + in + assert (Compare.Z.(total_size >= Z.zero)) ; + let prepaid_bootstrap_storage = + if prepaid_bootstrap_storage then total_size else Z.zero + in + Storage.Contract.Paid_storage_space.init + c + contract + prepaid_bootstrap_storage + >>=? fun c -> + Storage.Contract.Used_storage_space.init c contract total_size + | None -> + return c + +let raw_originate c ?prepaid_bootstrap_storage contract ~balance ~script + ~delegate = + create_base + c + ?prepaid_bootstrap_storage + contract + ~balance + ~manager:None + ~delegate + ~script + () + +let create_implicit c manager ~balance = + create_base + c + (Contract_repr.implicit_contract manager) + ~balance + ~manager:(Some manager) + ?script:None + ~delegate:None + () + +let delete c contract = + match Contract_repr.is_implicit contract with + | None -> + (* For non implicit contract Big_map should be cleared *) + failwith "Non implicit contracts cannot be removed" + | Some _ -> + Delegate_storage.remove c contract + >>=? fun c -> + Storage.Contract.Balance.remove_existing c contract + >>=? fun c -> + Storage.Contract.Manager.remove_existing c contract + >>=? fun c -> + Storage.Contract.Counter.remove_existing c contract + >>=? fun c -> + Storage.Contract.Code.remove c contract + >>=? fun (c, _, _) -> + Storage.Contract.Storage.remove c contract + >>=? fun (c, _, _) -> + Storage.Contract.Paid_storage_space.remove c contract + >>= fun c -> Storage.Contract.Used_storage_space.remove c contract >|= ok + +let allocated c contract = + Storage.Contract.Balance.find c contract + >>=? function None -> return_false | Some _ -> return_true + +let exists c contract = + match Contract_repr.is_implicit contract with + | Some _ -> + return_true + | None -> + allocated c contract + +let must_exist c contract = + exists c contract + >>=? function + | true -> return_unit | false -> fail (Non_existing_contract contract) + +let must_be_allocated c contract = + allocated c contract + >>=? function + | true -> + return_unit + | false -> ( + match Contract_repr.is_implicit contract with + | Some pkh -> + fail (Empty_implicit_contract pkh) + | None -> + fail (Non_existing_contract contract) ) + +let list c = Storage.Contract.list c + +let fresh_contract_from_current_nonce c = + Raw_context.increment_origination_nonce c + >|? fun (c, nonce) -> (c, Contract_repr.originated_contract nonce) + +let originated_from_current_nonce ~since:ctxt_since ~until:ctxt_until = + Raw_context.origination_nonce ctxt_since + >>?= fun since -> + Raw_context.origination_nonce ctxt_until + >>?= fun until -> + filter_s + (fun contract -> exists ctxt_until contract) + (Contract_repr.originated_contracts ~since ~until) + +let check_counter_increment c manager counter = + let contract = Contract_repr.implicit_contract manager in + Storage.Contract.Counter.get c contract + >>=? fun contract_counter -> + let expected = Z.succ contract_counter in + if Compare.Z.(expected = counter) then return_unit + else if Compare.Z.(expected > counter) then + fail (Counter_in_the_past (contract, expected, counter)) + else fail (Counter_in_the_future (contract, expected, counter)) + +let increment_counter c manager = + let contract = Contract_repr.implicit_contract manager in + Storage.Contract.Global_counter.get c + >>=? fun global_counter -> + Storage.Contract.Global_counter.update c (Z.succ global_counter) + >>=? fun c -> + Storage.Contract.Counter.get c contract + >>=? fun contract_counter -> + Storage.Contract.Counter.update c contract (Z.succ contract_counter) + +let get_script_code c contract = Storage.Contract.Code.find c contract + +let get_script c contract = + Storage.Contract.Code.find c contract + >>=? fun (c, code) -> + Storage.Contract.Storage.find c contract + >>=? fun (c, storage) -> + match (code, storage) with + | (None, None) -> + return (c, None) + | (Some code, Some storage) -> + return (c, Some {Script_repr.code; storage}) + | (None, Some _) | (Some _, None) -> + failwith "get_script" + +let get_storage ctxt contract = + Storage.Contract.Storage.find ctxt contract + >>=? function + | (ctxt, None) -> + return (ctxt, None) + | (ctxt, Some storage) -> + Lwt.return (Script_repr.force_decode storage) + >>=? fun (storage, cost) -> + Lwt.return (Raw_context.consume_gas ctxt cost) + >>=? fun ctxt -> return (ctxt, Some storage) + +let get_counter c manager = + let contract = Contract_repr.implicit_contract manager in + Storage.Contract.Counter.find c contract + >>=? function + | None -> ( + match Contract_repr.is_implicit contract with + | Some _ -> + Storage.Contract.Global_counter.get c + | None -> + failwith "get_counter" ) + | Some v -> + return v + +let get_manager_key c manager = + let contract = Contract_repr.implicit_contract manager in + Storage.Contract.Manager.find c contract + >>=? function + | None -> + failwith "get_manager_key" + | Some (Manager_repr.Hash _) -> + fail (Unrevealed_manager_key contract) + | Some (Manager_repr.Public_key v) -> + return v + +let is_manager_key_revealed c manager = + let contract = Contract_repr.implicit_contract manager in + Storage.Contract.Manager.find c contract + >>=? function + | None -> + return_false + | Some (Manager_repr.Hash _) -> + return_false + | Some (Manager_repr.Public_key _) -> + return_true + +let reveal_manager_key c manager public_key = + let contract = Contract_repr.implicit_contract manager in + Storage.Contract.Manager.get c contract + >>=? function + | Public_key _ -> + fail (Previously_revealed_key contract) + | Hash v -> + let actual_hash = Signature.Public_key.hash public_key in + if Signature.Public_key_hash.equal actual_hash v then + let v = Manager_repr.Public_key public_key in + Storage.Contract.Manager.update c contract v + else fail (Inconsistent_hash (public_key, v, actual_hash)) + +let get_balance c contract = + Storage.Contract.Balance.find c contract + >>=? function + | None -> ( + match Contract_repr.is_implicit contract with + | Some _ -> + return Tez_repr.zero + | None -> + failwith "get_balance" ) + | Some v -> + return v + +let get_balance_carbonated c contract = + (* Reading an int64 from /contracts/pkh/balance + NB: this cost assumes a flattened storage structure. *) + Raw_context.consume_gas + c + (Storage_costs.read_access ~path_length:3 ~read_bytes:8) + >>?= fun c -> get_balance c contract >>=? fun balance -> return (c, balance) + +let update_script_storage c contract storage lazy_storage_diff = + let storage = Script_repr.lazy_expr storage in + update_script_lazy_storage c lazy_storage_diff + >>=? fun (c, lazy_storage_size_diff) -> + Storage.Contract.Storage.update c contract storage + >>=? fun (c, size_diff) -> + Storage.Contract.Used_storage_space.get c contract + >>=? fun previous_size -> + let new_size = + Z.add previous_size (Z.add lazy_storage_size_diff (Z.of_int size_diff)) + in + Storage.Contract.Used_storage_space.update c contract new_size + +let spend c contract amount = + Storage.Contract.Balance.get c contract + >>=? fun balance -> + match Tez_repr.(balance -? amount) with + | Error _ -> + fail (Balance_too_low (contract, balance, amount)) + | Ok new_balance -> ( + Storage.Contract.Balance.update c contract new_balance + >>=? fun c -> + Roll_storage.Contract.remove_amount c contract amount + >>=? fun c -> + if Tez_repr.(new_balance > Tez_repr.zero) then return c + else + match Contract_repr.is_implicit contract with + | None -> + return c (* Never delete originated contracts *) + | Some pkh -> ( + Delegate_storage.get c contract + >>=? function + | Some pkh' -> + if Signature.Public_key_hash.equal pkh pkh' then return c + else + (* Delegated implicit accounts cannot be emptied *) + fail (Empty_implicit_delegated_contract pkh) + | None -> + (* Delete empty implicit contract *) + delete c contract ) ) + +let credit c contract amount = + ( if Tez_repr.(amount <> Tez_repr.zero) then return c + else + must_exist c contract + >>=? fun () -> + Storage.Contract.Code.mem c contract + >>=? fun (c, target_has_code) -> + Lwt.return + ( error_unless target_has_code (Empty_transaction contract) + >|? fun () -> c ) ) + >>=? fun c -> + Storage.Contract.Balance.find c contract + >>=? function + | None -> ( + match Contract_repr.is_implicit contract with + | None -> + fail (Non_existing_contract contract) + | Some manager -> + create_implicit c manager ~balance:amount ) + | Some balance -> + Tez_repr.(amount +? balance) + >>?= fun balance -> + Storage.Contract.Balance.update c contract balance + >>=? fun c -> Roll_storage.Contract.add_amount c contract amount + +let init c = + Storage.Contract.Global_counter.init c Z.zero + >>=? fun c -> Lazy_storage_diff.init c + +let used_storage_space c contract = + Storage.Contract.Used_storage_space.find c contract + >|=? Option.value ~default:Z.zero + +let paid_storage_space c contract = + Storage.Contract.Paid_storage_space.find c contract + >|=? Option.value ~default:Z.zero + +let set_paid_storage_space_and_return_fees_to_pay c contract new_storage_space + = + Storage.Contract.Paid_storage_space.get c contract + >>=? fun already_paid_space -> + if Compare.Z.(already_paid_space >= new_storage_space) then return (Z.zero, c) + else + let to_pay = Z.sub new_storage_space already_paid_space in + Storage.Contract.Paid_storage_space.update c contract new_storage_space + >|=? fun c -> (to_pay, c) diff --git a/src/proto_009_PsFLoren/lib_protocol/contract_storage.mli b/src/proto_009_PsFLoren/lib_protocol/contract_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..51cdccb40b08f75b138e4fab952f480968c6c44a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/contract_storage.mli @@ -0,0 +1,183 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Balance_too_low of Contract_repr.contract * Tez_repr.t * Tez_repr.t + | (* `Temporary *) + Counter_in_the_past of Contract_repr.contract * Z.t * Z.t + | (* `Branch *) + Counter_in_the_future of Contract_repr.contract * Z.t * Z.t + | (* `Temporary *) + Unspendable_contract of Contract_repr.contract + | (* `Permanent *) + Non_existing_contract of Contract_repr.contract + | (* `Temporary *) + Empty_implicit_contract of Signature.Public_key_hash.t + | (* `Temporary *) + Empty_implicit_delegated_contract of + Signature.Public_key_hash.t + | (* `Temporary *) + Empty_transaction of Contract_repr.t (* `Temporary *) + | Inconsistent_hash of + Signature.Public_key.t + * Signature.Public_key_hash.t + * Signature.Public_key_hash.t + | (* `Permanent *) + Inconsistent_public_key of + Signature.Public_key.t * Signature.Public_key.t + | (* `Permanent *) + Failure of string (* `Permanent *) + | Previously_revealed_key of Contract_repr.t (* `Permanent *) + | Unrevealed_manager_key of Contract_repr.t + +(* `Permanent *) + +val exists : Raw_context.t -> Contract_repr.t -> bool tzresult Lwt.t + +val must_exist : Raw_context.t -> Contract_repr.t -> unit tzresult Lwt.t + +val allocated : Raw_context.t -> Contract_repr.t -> bool tzresult Lwt.t + +val must_be_allocated : Raw_context.t -> Contract_repr.t -> unit tzresult Lwt.t + +val list : Raw_context.t -> Contract_repr.t list Lwt.t + +val check_counter_increment : + Raw_context.t -> Signature.Public_key_hash.t -> Z.t -> unit tzresult Lwt.t + +val increment_counter : + Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t + +val get_manager_key : + Raw_context.t -> + Signature.Public_key_hash.t -> + Signature.Public_key.t tzresult Lwt.t + +val is_manager_key_revealed : + Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + +val reveal_manager_key : + Raw_context.t -> + Signature.Public_key_hash.t -> + Signature.Public_key.t -> + Raw_context.t tzresult Lwt.t + +val get_balance : Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t + +val get_balance_carbonated : + Raw_context.t -> + Contract_repr.t -> + (Raw_context.t * Tez_repr.t) tzresult Lwt.t + +val get_counter : + Raw_context.t -> Signature.Public_key_hash.t -> Z.t tzresult Lwt.t + +val get_script_code : + Raw_context.t -> + Contract_repr.t -> + (Raw_context.t * Script_repr.lazy_expr option) tzresult Lwt.t + +val get_script : + Raw_context.t -> + Contract_repr.t -> + (Raw_context.t * Script_repr.t option) tzresult Lwt.t + +val get_storage : + Raw_context.t -> + Contract_repr.t -> + (Raw_context.t * Script_repr.expr option) tzresult Lwt.t + +module Legacy_big_map_diff : sig + type item = private + | Update of { + big_map : Z.t; + diff_key : Script_repr.expr; + diff_key_hash : Script_expr_hash.t; + diff_value : Script_repr.expr option; + } + | Clear of Z.t + | Copy of {src : Z.t; dst : Z.t} + | Alloc of { + big_map : Z.t; + key_type : Script_repr.expr; + value_type : Script_repr.expr; + } + + type t = item list + + val encoding : t Data_encoding.t + + val to_lazy_storage_diff : t -> Lazy_storage_diff.diffs + + val of_lazy_storage_diff : Lazy_storage_diff.diffs -> t +end + +val update_script_storage : + Raw_context.t -> + Contract_repr.t -> + Script_repr.expr -> + Lazy_storage_diff.diffs option -> + Raw_context.t tzresult Lwt.t + +val credit : + Raw_context.t -> + Contract_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val spend : + Raw_context.t -> + Contract_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val raw_originate : + Raw_context.t -> + ?prepaid_bootstrap_storage:bool -> + Contract_repr.t -> + balance:Tez_repr.t -> + script:Script_repr.t * Lazy_storage_diff.diffs option -> + delegate:Signature.Public_key_hash.t option -> + Raw_context.t tzresult Lwt.t + +val fresh_contract_from_current_nonce : + Raw_context.t -> (Raw_context.t * Contract_repr.t) tzresult + +val originated_from_current_nonce : + since:Raw_context.t -> + until:Raw_context.t -> + Contract_repr.t list tzresult Lwt.t + +val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + +val used_storage_space : Raw_context.t -> Contract_repr.t -> Z.t tzresult Lwt.t + +val paid_storage_space : Raw_context.t -> Contract_repr.t -> Z.t tzresult Lwt.t + +val set_paid_storage_space_and_return_fees_to_pay : + Raw_context.t -> + Contract_repr.t -> + Z.t -> + (Z.t * Raw_context.t) tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/coq-of-ocaml/README.md b/src/proto_009_PsFLoren/lib_protocol/coq-of-ocaml/README.md new file mode 100644 index 0000000000000000000000000000000000000000..893cce94c04ad695312978422717a55ee9064277 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/coq-of-ocaml/README.md @@ -0,0 +1,6 @@ +# coq-of-ocaml + +In this folder we put the files relevant to the compilation of the protocol to Coq using [coq-of-ocaml](https://clarus.github.io/coq-of-ocaml/). For support, you can contact Guillaume Claret at `dev@clarus.me`. + +* `config.json` This file describes the configuration parameters for coq-of-ocaml in the CI. For more information, see the [documentation](https://clarus.github.io/coq-of-ocaml/docs/configuration). + diff --git a/src/proto_009_PsFLoren/lib_protocol/coq-of-ocaml/config.json b/src/proto_009_PsFLoren/lib_protocol/coq-of-ocaml/config.json new file mode 100644 index 0000000000000000000000000000000000000000..60d5c932ef577fd31b143b5d0a12655f4c4593a1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/coq-of-ocaml/config.json @@ -0,0 +1,133 @@ +{ + "alias_barrier_modules": [ + "Tezos_protocol_environment_alpha__Environment" + ], + "constructor_map": [ + ["public_key_hash", "Ed25519", "Ed25519Hash"], + ["public_key_hash", "P256", "P256Hash"], + ["public_key_hash", "Secp256k1", "Secp256k1Hash"] + ], + "error_category_blacklist": [ + "extensible_type", + "module", + "side_effect" + ], + "error_filename_blacklist": [ + "apply.ml", + "contract_hash.ml", + "contract_repr.ml", + "helpers_services.ml", + "lazy_storage_kind.ml", + "level_repr.ml", + "main.mli", + "misc.ml", + "nonce_hash.ml", + "script_expr_hash.ml", + "script_ir_translator.ml", + "state_hash.ml", + "storage_functors.ml", + "storage.ml", + "voting_period_repr.ml" + ], + "error_message_blacklist": [ + "Unbound module Tezos_protocol_009_PsFLoren_functor" + ], + "escape_value": [ + "a", + "b", + "baking_rights_query", + "case", + "cons", + "descr", + "elt", + "endorsing_rights_query", + "eq", + "error", + "field", + "fixed", + "frozen_balance", + "handler", + "hash", + "info", + "internal_gas", + "json", + "json_schema", + "judgement", + "key", + "lazy_expr", + "level_query", + "list_query", + "nonce", + "query", + "p", + "parametric", + "r", + "raw", + "seed", + "sequence", + "snapshot", + "stack", + "storage_error", + "t", + "tc_context", + "type_logger" + ], + "first_class_module_path_blacklist": [ + "Tezos_raw_protocol_009_PsFLoren" + ], + "head_suffix": "Import Environment.Notations.\n", + "monadic_operators": [ + ["Error_monad.op_gtgteq", "let="], + ["Error_monad.op_gtgteqquestion", "let=?"], + ["Error_monad.op_gtgtquestion", "let?"] + ], + "require": [ + ["Tezos_raw_protocol_009_PsFLoren", "TezosOfOCaml.Proto_alpha"] + ], + "require_import": [ + ["Tezos_protocol_environment_alpha", "TezosOfOCaml.Proto_alpha"] + ], + "require_long_ident": [ + ["Storage_description", "TezosOfOCaml.Proto_alpha"] + ], + "require_mli": [ + "Storage", + "Storage_functors" + ], + "variant_constructors": [ + ["Dir", "Context.Dir"], + ["Key", "Context.Key"], + ["Uint16", "Data_encoding.Uint16"], + ["Uint8", "Data_encoding.Uint8"], + ["Hex", "MBytes.Hex"] + ], + "variant_types": [ + ["Dir", "Context.key_or_dir"], + ["Key", "Context.key_or_dir"] + ], + "without_guard_checking": [ + "apply.ml", + "apply_results.ml", + "baking.ml", + "contract_repr.ml", + "legacy_script_support_repr.ml", + "level_storage.ml", + "michelson_v1_gas.ml", + "michelson_v1_primitives.ml", + "misc.ml", + "operation_repr.ml", + "qty_repr.ml", + "raw_context.ml", + "roll_storage.ml", + "script_interpreter.ml", + "script_ir_annot.ml", + "script_ir_translator.ml", + "script_repr.ml", + "seed_repr.ml", + "storage_description.ml", + "storage_functors.ml" + ], + "without_positivity_checking": [ + "storage_description.ml" + ] +} diff --git a/src/proto_009_PsFLoren/lib_protocol/cycle_repr.ml b/src/proto_009_PsFLoren/lib_protocol/cycle_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..2b58e176923dab9dea8166fe82b419bc7f0896d9 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/cycle_repr.ml @@ -0,0 +1,86 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = int32 + +type cycle = t + +let encoding = Data_encoding.int32 + +let rpc_arg = + let construct = Int32.to_string in + let destruct str = + Int32.of_string_opt str |> Option.to_result ~none:"Cannot parse cycle" + in + RPC_arg.make + ~descr:"A cycle integer" + ~name:"block_cycle" + ~construct + ~destruct + () + +let pp ppf cycle = Format.fprintf ppf "%ld" cycle + +include (Compare.Int32 : Compare.S with type t := t) + +module Map = Map.Make (Compare.Int32) + +let root = 0l + +let succ = Int32.succ + +let pred = function 0l -> None | i -> Some (Int32.pred i) + +let add c i = + assert (Compare.Int.(i >= 0)) ; + Int32.add c (Int32.of_int i) + +let sub c i = + assert (Compare.Int.(i >= 0)) ; + let r = Int32.sub c (Int32.of_int i) in + if Compare.Int32.(r < 0l) then None else Some r + +let to_int32 i = i + +let of_int32_exn l = + if Compare.Int32.(l >= 0l) then l + else invalid_arg "Level_repr.Cycle.of_int32" + +module Index = struct + type t = cycle + + let path_length = 1 + + let to_path c l = Int32.to_string (to_int32 c) :: l + + let of_path = function [s] -> Int32.of_string_opt s | _ -> None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_009_PsFLoren/lib_protocol/cycle_repr.mli b/src/proto_009_PsFLoren/lib_protocol/cycle_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..241992c708fdb4f27f4267063f7cd0e2d42ef882 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/cycle_repr.mli @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t + +type cycle = t + +include Compare.S with type t := t + +val encoding : cycle Data_encoding.t + +val rpc_arg : cycle RPC_arg.arg + +val pp : Format.formatter -> cycle -> unit + +val root : cycle + +val pred : cycle -> cycle option + +val add : cycle -> int -> cycle + +val sub : cycle -> int -> cycle option + +val succ : cycle -> cycle + +val to_int32 : cycle -> int32 + +val of_int32_exn : int32 -> cycle + +module Map : S.MAP with type key = cycle + +module Index : Storage_description.INDEX with type t = cycle diff --git a/src/proto_009_PsFLoren/lib_protocol/delegate_services.ml b/src/proto_009_PsFLoren/lib_protocol/delegate_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..1c3a6a7b28975a56344d0f383a3954244ea9f457 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/delegate_services.ml @@ -0,0 +1,765 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type info = { + balance : Tez.t; + frozen_balance : Tez.t; + frozen_balance_by_cycle : Delegate.frozen_balance Cycle.Map.t; + staking_balance : Tez.t; + delegated_contracts : Contract.t list; + delegated_balance : Tez.t; + deactivated : bool; + grace_period : Cycle.t; + voting_power : int32; +} + +let info_encoding = + let open Data_encoding in + conv + (fun { balance; + frozen_balance; + frozen_balance_by_cycle; + staking_balance; + delegated_contracts; + delegated_balance; + deactivated; + grace_period; + voting_power } -> + ( balance, + frozen_balance, + frozen_balance_by_cycle, + staking_balance, + delegated_contracts, + delegated_balance, + deactivated, + grace_period, + voting_power )) + (fun ( balance, + frozen_balance, + frozen_balance_by_cycle, + staking_balance, + delegated_contracts, + delegated_balance, + deactivated, + grace_period, + voting_power ) -> + { + balance; + frozen_balance; + frozen_balance_by_cycle; + staking_balance; + delegated_contracts; + delegated_balance; + deactivated; + grace_period; + voting_power; + }) + (obj9 + (req "balance" Tez.encoding) + (req "frozen_balance" Tez.encoding) + (req "frozen_balance_by_cycle" Delegate.frozen_balance_by_cycle_encoding) + (req "staking_balance" Tez.encoding) + (req "delegated_contracts" (list Contract.encoding)) + (req "delegated_balance" Tez.encoding) + (req "deactivated" bool) + (req "grace_period" Cycle.encoding) + (req "voting_power" int32)) + +module S = struct + let path = RPC_path.(open_root / "context" / "delegates") + + open Data_encoding + + type list_query = {active : bool; inactive : bool} + + let list_query : list_query RPC_query.t = + let open RPC_query in + query (fun active inactive -> {active; inactive}) + |+ flag "active" (fun t -> t.active) + |+ flag "inactive" (fun t -> t.inactive) + |> seal + + let list_delegate = + RPC_service.get_service + ~description:"Lists all registered delegates." + ~query:list_query + ~output:(list Signature.Public_key_hash.encoding) + path + + let path = RPC_path.(path /: Signature.Public_key_hash.rpc_arg) + + let info = + RPC_service.get_service + ~description:"Everything about a delegate." + ~query:RPC_query.empty + ~output:info_encoding + path + + let balance = + RPC_service.get_service + ~description: + "Returns the full balance of a given delegate, including the frozen \ + balances." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "balance") + + let frozen_balance = + RPC_service.get_service + ~description: + "Returns the total frozen balances of a given delegate, this includes \ + the frozen deposits, rewards and fees." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "frozen_balance") + + let frozen_balance_by_cycle = + RPC_service.get_service + ~description: + "Returns the frozen balances of a given delegate, indexed by the \ + cycle by which it will be unfrozen" + ~query:RPC_query.empty + ~output:Delegate.frozen_balance_by_cycle_encoding + RPC_path.(path / "frozen_balance_by_cycle") + + let staking_balance = + RPC_service.get_service + ~description: + "Returns the total amount of tokens delegated to a given delegate. \ + This includes the balances of all the contracts that delegate to it, \ + but also the balance of the delegate itself and its frozen fees and \ + deposits. The rewards do not count in the delegated balance until \ + they are unfrozen." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "staking_balance") + + let delegated_contracts = + RPC_service.get_service + ~description: + "Returns the list of contracts that delegate to a given delegate." + ~query:RPC_query.empty + ~output:(list Contract.encoding) + RPC_path.(path / "delegated_contracts") + + let delegated_balance = + RPC_service.get_service + ~description: + "Returns the balances of all the contracts that delegate to a given \ + delegate. This excludes the delegate's own balance and its frozen \ + balances." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "delegated_balance") + + let deactivated = + RPC_service.get_service + ~description: + "Tells whether the delegate is currently tagged as deactivated or not." + ~query:RPC_query.empty + ~output:bool + RPC_path.(path / "deactivated") + + let grace_period = + RPC_service.get_service + ~description: + "Returns the cycle by the end of which the delegate might be \ + deactivated if she fails to execute any delegate action. A \ + deactivated delegate might be reactivated (without loosing any \ + rolls) by simply re-registering as a delegate. For deactivated \ + delegates, this value contains the cycle by which they were \ + deactivated." + ~query:RPC_query.empty + ~output:Cycle.encoding + RPC_path.(path / "grace_period") + + let voting_power = + RPC_service.get_service + ~description: + "The number of rolls in the vote listings for a given delegate" + ~query:RPC_query.empty + ~output:Data_encoding.int32 + RPC_path.(path / "voting_power") +end + +let register () = + let open Services_registration in + register0 S.list_delegate (fun ctxt q () -> + Delegate.list ctxt + >>= fun delegates -> + match q with + | {active = true; inactive = false} -> + filter_s + (fun pkh -> Delegate.deactivated ctxt pkh >|=? not) + delegates + | {active = false; inactive = true} -> + filter_s (fun pkh -> Delegate.deactivated ctxt pkh) delegates + | _ -> + return delegates) ; + register1 S.info (fun ctxt pkh () () -> + Delegate.full_balance ctxt pkh + >>=? fun balance -> + Delegate.frozen_balance ctxt pkh + >>=? fun frozen_balance -> + Delegate.frozen_balance_by_cycle ctxt pkh + >>= fun frozen_balance_by_cycle -> + Delegate.staking_balance ctxt pkh + >>=? fun staking_balance -> + Delegate.delegated_contracts ctxt pkh + >>= fun delegated_contracts -> + Delegate.delegated_balance ctxt pkh + >>=? fun delegated_balance -> + Delegate.deactivated ctxt pkh + >>=? fun deactivated -> + Delegate.grace_period ctxt pkh + >>=? fun grace_period -> + Vote.get_voting_power_free ctxt pkh + >|=? fun voting_power -> + { + balance; + frozen_balance; + frozen_balance_by_cycle; + staking_balance; + delegated_contracts; + delegated_balance; + deactivated; + grace_period; + voting_power; + }) ; + register1 S.balance (fun ctxt pkh () () -> Delegate.full_balance ctxt pkh) ; + register1 S.frozen_balance (fun ctxt pkh () () -> + Delegate.frozen_balance ctxt pkh) ; + register1 S.frozen_balance_by_cycle (fun ctxt pkh () () -> + Delegate.frozen_balance_by_cycle ctxt pkh >|= ok) ; + register1 S.staking_balance (fun ctxt pkh () () -> + Delegate.staking_balance ctxt pkh) ; + register1 S.delegated_contracts (fun ctxt pkh () () -> + Delegate.delegated_contracts ctxt pkh >|= ok) ; + register1 S.delegated_balance (fun ctxt pkh () () -> + Delegate.delegated_balance ctxt pkh) ; + register1 S.deactivated (fun ctxt pkh () () -> Delegate.deactivated ctxt pkh) ; + register1 S.grace_period (fun ctxt pkh () () -> + Delegate.grace_period ctxt pkh) ; + register1 S.voting_power (fun ctxt pkh () () -> + Vote.get_voting_power_free ctxt pkh) + +let list ctxt block ?(active = true) ?(inactive = false) () = + RPC_context.make_call0 S.list_delegate ctxt block {active; inactive} () + +let info ctxt block pkh = RPC_context.make_call1 S.info ctxt block pkh () () + +let balance ctxt block pkh = + RPC_context.make_call1 S.balance ctxt block pkh () () + +let frozen_balance ctxt block pkh = + RPC_context.make_call1 S.frozen_balance ctxt block pkh () () + +let frozen_balance_by_cycle ctxt block pkh = + RPC_context.make_call1 S.frozen_balance_by_cycle ctxt block pkh () () + +let staking_balance ctxt block pkh = + RPC_context.make_call1 S.staking_balance ctxt block pkh () () + +let delegated_contracts ctxt block pkh = + RPC_context.make_call1 S.delegated_contracts ctxt block pkh () () + +let delegated_balance ctxt block pkh = + RPC_context.make_call1 S.delegated_balance ctxt block pkh () () + +let deactivated ctxt block pkh = + RPC_context.make_call1 S.deactivated ctxt block pkh () () + +let grace_period ctxt block pkh = + RPC_context.make_call1 S.grace_period ctxt block pkh () () + +let voting_power ctxt block pkh = + RPC_context.make_call1 S.voting_power ctxt block pkh () () + +let requested_levels ~default ctxt cycles levels = + match (levels, cycles) with + | ([], []) -> + ok [default] + | (levels, cycles) -> + (* explicitly fail when requested levels or cycle are in the past... + or too far in the future... *) + let levels = + List.sort_uniq + Level.compare + (List.concat + ( List.map (Level.from_raw ctxt) levels + :: List.map (Level.levels_in_cycle ctxt) cycles )) + in + map + (fun level -> + let current_level = Level.current ctxt in + if Level.(level <= current_level) then ok (level, None) + else + Baking.earlier_predecessor_timestamp ctxt level + >|? fun timestamp -> (level, Some timestamp)) + levels + +module Baking_rights = struct + type t = { + level : Raw_level.t; + delegate : Signature.Public_key_hash.t; + priority : int; + timestamp : Timestamp.t option; + } + + let encoding = + let open Data_encoding in + conv + (fun {level; delegate; priority; timestamp} -> + (level, delegate, priority, timestamp)) + (fun (level, delegate, priority, timestamp) -> + {level; delegate; priority; timestamp}) + (obj4 + (req "level" Raw_level.encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "priority" uint16) + (opt "estimated_time" Timestamp.encoding)) + + module S = struct + open Data_encoding + + let custom_root = RPC_path.(open_root / "helpers" / "baking_rights") + + type baking_rights_query = { + levels : Raw_level.t list; + cycles : Cycle.t list; + delegates : Signature.Public_key_hash.t list; + max_priority : int option; + all : bool; + } + + let baking_rights_query = + let open RPC_query in + query (fun levels cycles delegates max_priority all -> + {levels; cycles; delegates; max_priority; all}) + |+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels) + |+ multi_field "cycle" Cycle.rpc_arg (fun t -> t.cycles) + |+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> + t.delegates) + |+ opt_field "max_priority" RPC_arg.int (fun t -> t.max_priority) + |+ flag "all" (fun t -> t.all) + |> seal + + let baking_rights = + RPC_service.get_service + ~description: + "Retrieves the list of delegates allowed to bake a block.\n\ + By default, it gives the best baking priorities for bakers that \ + have at least one opportunity below the 64th priority for the next \ + block.\n\ + Parameters `level` and `cycle` can be used to specify the (valid) \ + level(s) in the past or future at which the baking rights have to \ + be returned. When asked for (a) whole cycle(s), baking \ + opportunities are given by default up to the priority 8.\n\ + Parameter `delegate` can be used to restrict the results to the \ + given delegates. If parameter `all` is set, all the baking \ + opportunities for each baker at each level are returned, instead \ + of just the first one.\n\ + Returns the list of baking slots. Also returns the minimal \ + timestamps that correspond to these slots. The timestamps are \ + omitted for levels in the past, and are only estimates for levels \ + later that the next block, based on the hypothesis that all \ + predecessor blocks were baked at the first priority." + ~query:baking_rights_query + ~output:(list encoding) + custom_root + end + + let baking_priorities ctxt max_prio (level, pred_timestamp) = + Baking.baking_priorities ctxt level + >>=? fun contract_list -> + let rec loop l acc priority = + if Compare.Int.(priority > max_prio) then return (List.rev acc) + else + let (Misc.LCons (pk, next)) = l in + let delegate = Signature.Public_key.hash pk in + ( match pred_timestamp with + | None -> + ok_none + | Some pred_timestamp -> + Baking.minimal_time ctxt priority pred_timestamp + >|? fun t -> Some t ) + >>?= fun timestamp -> + let acc = + {level = level.level; delegate; priority; timestamp} :: acc + in + next () >>=? fun l -> loop l acc (priority + 1) + in + loop contract_list [] 0 + + let baking_priorities_of_delegates ctxt ~all ~max_prio delegates + (level, pred_timestamp) = + Baking.baking_priorities ctxt level + >>=? fun contract_list -> + let rec loop l acc priority delegates = + match delegates with + | [] -> + return (List.rev acc) + | _ :: _ -> ( + if Compare.Int.(priority > max_prio) then return (List.rev acc) + else + let (Misc.LCons (pk, next)) = l in + next () + >>=? fun l -> + match + List.partition + (fun (pk', _) -> Signature.Public_key.equal pk pk') + delegates + with + | ([], _) -> + loop l acc (priority + 1) delegates + | ((_, delegate) :: _, delegates') -> + ( match pred_timestamp with + | None -> + ok_none + | Some pred_timestamp -> + Baking.minimal_time ctxt priority pred_timestamp + >|? fun t -> Some t ) + >>?= fun timestamp -> + let acc = + {level = level.level; delegate; priority; timestamp} :: acc + in + let delegates'' = if all then delegates else delegates' in + loop l acc (priority + 1) delegates'' ) + in + loop contract_list [] 0 delegates + + let remove_duplicated_delegates rights = + List.rev @@ fst + @@ List.fold_left + (fun (acc, previous) r -> + if Signature.Public_key_hash.Set.mem r.delegate previous then + (acc, previous) + else + (r :: acc, Signature.Public_key_hash.Set.add r.delegate previous)) + ([], Signature.Public_key_hash.Set.empty) + rights + + let register () = + let open Services_registration in + register0 S.baking_rights (fun ctxt q () -> + requested_levels + ~default: + ( Level.succ ctxt (Level.current ctxt), + Some (Timestamp.current ctxt) ) + ctxt + q.cycles + q.levels + >>?= fun levels -> + let max_priority = + match q.max_priority with + | Some max -> + max + | None -> ( + match q.cycles with [] -> 64 | _ :: _ -> 8 ) + in + match q.delegates with + | [] -> + map_s (baking_priorities ctxt max_priority) levels + >|=? fun rights -> + let rights = + if q.all then rights + else List.map remove_duplicated_delegates rights + in + List.concat rights + | _ :: _ as delegates -> + Lwt_list.filter_map_s + (fun delegate -> + Contract.get_manager_key ctxt delegate + >>= function + | Ok pk -> + Lwt.return (Some (pk, delegate)) + | Error _ -> + Lwt.return_none) + delegates + >>= fun delegates -> + map_s + (fun level -> + baking_priorities_of_delegates + ctxt + q.all + max_priority + delegates + level) + levels + >|=? List.concat) + + let get ctxt ?(levels = []) ?(cycles = []) ?(delegates = []) ?(all = false) + ?max_priority block = + RPC_context.make_call0 + S.baking_rights + ctxt + block + {levels; cycles; delegates; max_priority; all} + () +end + +module Endorsing_rights = struct + type t = { + level : Raw_level.t; + delegate : Signature.Public_key_hash.t; + slots : int list; + estimated_time : Time.t option; + } + + let encoding = + let open Data_encoding in + conv + (fun {level; delegate; slots; estimated_time} -> + (level, delegate, slots, estimated_time)) + (fun (level, delegate, slots, estimated_time) -> + {level; delegate; slots; estimated_time}) + (obj4 + (req "level" Raw_level.encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "slots" (list uint16)) + (opt "estimated_time" Timestamp.encoding)) + + module S = struct + open Data_encoding + + let custom_root = RPC_path.(open_root / "helpers" / "endorsing_rights") + + type endorsing_rights_query = { + levels : Raw_level.t list; + cycles : Cycle.t list; + delegates : Signature.Public_key_hash.t list; + } + + let endorsing_rights_query = + let open RPC_query in + query (fun levels cycles delegates -> {levels; cycles; delegates}) + |+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels) + |+ multi_field "cycle" Cycle.rpc_arg (fun t -> t.cycles) + |+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> + t.delegates) + |> seal + + let endorsing_rights = + RPC_service.get_service + ~description: + "Retrieves the delegates allowed to endorse a block.\n\ + By default, it gives the endorsement slots for delegates that have \ + at least one in the next block.\n\ + Parameters `level` and `cycle` can be used to specify the (valid) \ + level(s) in the past or future at which the endorsement rights \ + have to be returned. Parameter `delegate` can be used to restrict \ + the results to the given delegates.\n\ + Returns the list of endorsement slots. Also returns the minimal \ + timestamps that correspond to these slots. The timestamps are \ + omitted for levels in the past, and are only estimates for levels \ + later that the next block, based on the hypothesis that all \ + predecessor blocks were baked at the first priority." + ~query:endorsing_rights_query + ~output:(list encoding) + custom_root + end + + let endorsement_slots ctxt (level, estimated_time) = + Baking.endorsement_rights ctxt level + >|=? fun rights -> + Signature.Public_key_hash.Map.fold + (fun delegate (_, slots, _) acc -> + {level = level.level; delegate; slots; estimated_time} :: acc) + rights + [] + + let register () = + let open Services_registration in + register0 S.endorsing_rights (fun ctxt q () -> + requested_levels + ~default:(Level.current ctxt, Some (Timestamp.current ctxt)) + ctxt + q.cycles + q.levels + >>?= fun levels -> + map_s (endorsement_slots ctxt) levels + >|=? fun rights -> + let rights = List.concat rights in + match q.delegates with + | [] -> + rights + | _ :: _ as delegates -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.delegate) + delegates + in + List.filter is_requested rights) + + let get ctxt ?(levels = []) ?(cycles = []) ?(delegates = []) block = + RPC_context.make_call0 + S.endorsing_rights + ctxt + block + {levels; cycles; delegates} + () +end + +module Endorsing_power = struct + let endorsing_power ctxt (operation, chain_id) = + let (Operation_data data) = operation.protocol_data in + match data.contents with + | Single (Endorsement_with_slot {endorsement; slot}) -> + Baking.check_endorsement_rights ctxt chain_id endorsement ~slot + >|=? fun (_, slots, _) -> List.length slots + | _ -> + failwith "Operation is not a wrapped endorsement" + + module S = struct + let endorsing_power = + let open Data_encoding in + RPC_service.post_service + ~description: + "Get the endorsing power of an endorsement, that is, the number of \ + slots that the endorser has" + ~query:RPC_query.empty + ~input: + (obj2 + (req "endorsement_operation" Operation.encoding) + (req "chain_id" Chain_id.encoding)) + ~output:int31 + RPC_path.(open_root / "endorsing_power") + end + + let register () = + let open Services_registration in + register0 S.endorsing_power (fun ctxt () (op, chain_id) -> + endorsing_power ctxt (op, chain_id)) + + let get ctxt block op chain_id = + RPC_context.make_call0 S.endorsing_power ctxt block () (op, chain_id) +end + +module Required_endorsements = struct + let required_endorsements ctxt block_delay = + Baking.minimum_allowed_endorsements ctxt ~block_delay + + module S = struct + type t = {block_delay : Period.t} + + let required_endorsements_query = + let open RPC_query in + query (fun block_delay -> {block_delay}) + |+ field "block_delay" Period.rpc_arg Period.zero (fun t -> + t.block_delay) + |> seal + + let required_endorsements = + let open Data_encoding in + RPC_service.get_service + ~description: + "Minimum number of endorsements for a block to be valid, given a \ + delay of the block's timestamp with respect to the minimum time to \ + bake at the block's priority" + ~query:required_endorsements_query + ~output:int31 + RPC_path.(open_root / "required_endorsements") + end + + let register () = + let open Services_registration in + register0 S.required_endorsements (fun ctxt {block_delay} () -> + return @@ required_endorsements ctxt block_delay) + + let get ctxt block block_delay = + RPC_context.make_call0 S.required_endorsements ctxt block {block_delay} () +end + +module Minimal_valid_time = struct + let minimal_valid_time ctxt ~priority ~endorsing_power = + Baking.minimal_valid_time ctxt ~priority ~endorsing_power + + module S = struct + type t = {priority : int; endorsing_power : int} + + let minimal_valid_time_query = + let open RPC_query in + query (fun priority endorsing_power -> {priority; endorsing_power}) + |+ field "priority" RPC_arg.int 0 (fun t -> t.priority) + |+ field "endorsing_power" RPC_arg.int 0 (fun t -> t.endorsing_power) + |> seal + + let minimal_valid_time = + RPC_service.get_service + ~description: + "Minimal valid time for a block given a priority and an endorsing \ + power." + ~query:minimal_valid_time_query + ~output:Time.encoding + RPC_path.(open_root / "minimal_valid_time") + end + + let register () = + let open Services_registration in + register0 S.minimal_valid_time (fun ctxt {priority; endorsing_power} () -> + Lwt.return @@ minimal_valid_time ctxt ~priority ~endorsing_power) + + let get ctxt block priority endorsing_power = + RPC_context.make_call0 + S.minimal_valid_time + ctxt + block + {priority; endorsing_power} + () +end + +let register () = + register () ; + Baking_rights.register () ; + Endorsing_rights.register () ; + Endorsing_power.register () ; + Required_endorsements.register () ; + Minimal_valid_time.register () + +let endorsement_rights ctxt level = + Endorsing_rights.endorsement_slots ctxt (level, None) + >|=? fun l -> List.map (fun {Endorsing_rights.delegate; _} -> delegate) l + +let baking_rights ctxt max_priority = + let max = match max_priority with None -> 64 | Some m -> m in + let level = Level.current ctxt in + Baking_rights.baking_priorities ctxt max (level, None) + >|=? fun l -> + ( level.level, + List.map + (fun {Baking_rights.delegate; timestamp; _} -> (delegate, timestamp)) + l ) + +let endorsing_power ctxt operation = + Endorsing_power.endorsing_power ctxt operation + +let required_endorsements ctxt delay = + Required_endorsements.required_endorsements ctxt delay + +let minimal_valid_time ctxt priority endorsing_power = + Minimal_valid_time.minimal_valid_time ctxt priority endorsing_power diff --git a/src/proto_009_PsFLoren/lib_protocol/delegate_services.mli b/src/proto_009_PsFLoren/lib_protocol/delegate_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..f8ec3fd7426412e60ca1ba26ca66880bd9d1a642 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/delegate_services.mli @@ -0,0 +1,215 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +val list : + 'a #RPC_context.simple -> + 'a -> + ?active:bool -> + ?inactive:bool -> + unit -> + Signature.Public_key_hash.t list shell_tzresult Lwt.t + +type info = { + balance : Tez.t; + frozen_balance : Tez.t; + frozen_balance_by_cycle : Delegate.frozen_balance Cycle.Map.t; + staking_balance : Tez.t; + delegated_contracts : Contract.t list; + delegated_balance : Tez.t; + deactivated : bool; + grace_period : Cycle.t; + voting_power : int32; +} + +val info_encoding : info Data_encoding.t + +val info : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + info shell_tzresult Lwt.t + +val balance : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t shell_tzresult Lwt.t + +val frozen_balance : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t shell_tzresult Lwt.t + +val frozen_balance_by_cycle : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Delegate.frozen_balance Cycle.Map.t shell_tzresult Lwt.t + +val staking_balance : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t shell_tzresult Lwt.t + +val delegated_contracts : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Contract.t list shell_tzresult Lwt.t + +val delegated_balance : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t shell_tzresult Lwt.t + +val deactivated : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + bool shell_tzresult Lwt.t + +val grace_period : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Cycle.t shell_tzresult Lwt.t + +val voting_power : + 'a #RPC_context.simple -> 'a -> public_key_hash -> int32 shell_tzresult Lwt.t + +module Baking_rights : sig + type t = { + level : Raw_level.t; + delegate : Signature.Public_key_hash.t; + priority : int; + timestamp : Timestamp.t option; + } + + (** Retrieves the list of delegates allowed to bake a block. + + By default, it gives the best baking priorities for bakers + that have at least one opportunity below the 64th priority for + the next block. + + Parameters [levels] and [cycles] can be used to specify the + (valid) level(s) in the past or future at which the baking rights + have to be returned. Parameter [delegates] can be used to + restrict the results to the given delegates. If parameter [all] + is [true], all the baking opportunities for each baker at each level + are returned, instead of just the first one. + + Returns the list of baking slots. Also returns the minimal + timestamps that correspond to these slots. The timestamps are + omitted for levels in the past, and are only estimates for levels + later that the next block, based on the hypothesis that all + predecessor blocks were baked at the first priority. *) + val get : + 'a #RPC_context.simple -> + ?levels:Raw_level.t list -> + ?cycles:Cycle.t list -> + ?delegates:Signature.public_key_hash list -> + ?all:bool -> + ?max_priority:int -> + 'a -> + t list shell_tzresult Lwt.t +end + +module Endorsing_rights : sig + type t = { + level : Raw_level.t; + delegate : Signature.Public_key_hash.t; + slots : int list; + estimated_time : Timestamp.t option; + } + + (** Retrieves the delegates allowed to endorse a block. + + By default, it gives the endorsement slots for bakers that have + at least one in the next block. + + Parameters [levels] and [cycles] can be used to specify the + (valid) level(s) in the past or future at which the endorsement + rights have to be returned. Parameter [delegates] can be used to + restrict the results to the given delegates. Returns the list of + endorsement slots. Also returns the minimal timestamps that + correspond to these slots. + + Timestamps are omitted for levels in the past, and are only + estimates for levels later that the next block, based on the + hypothesis that all predecessor blocks were baked at the first + priority. *) + val get : + 'a #RPC_context.simple -> + ?levels:Raw_level.t list -> + ?cycles:Cycle.t list -> + ?delegates:Signature.public_key_hash list -> + 'a -> + t list shell_tzresult Lwt.t +end + +module Endorsing_power : sig + val get : + 'a #RPC_context.simple -> + 'a -> + Alpha_context.packed_operation -> + Chain_id.t -> + int shell_tzresult Lwt.t +end + +module Required_endorsements : sig + val get : + 'a #RPC_context.simple -> 'a -> Period.t -> int shell_tzresult Lwt.t +end + +module Minimal_valid_time : sig + val get : + 'a #RPC_context.simple -> 'a -> int -> int -> Time.t shell_tzresult Lwt.t +end + +(* temporary export for deprecated unit test *) +val endorsement_rights : + Alpha_context.t -> Level.t -> public_key_hash list tzresult Lwt.t + +val baking_rights : + Alpha_context.t -> + int option -> + (Raw_level.t * (public_key_hash * Time.t option) list) tzresult Lwt.t + +val endorsing_power : + Alpha_context.t -> + Alpha_context.packed_operation * Chain_id.t -> + int tzresult Lwt.t + +val required_endorsements : Alpha_context.t -> Alpha_context.Period.t -> int + +val minimal_valid_time : Alpha_context.t -> int -> int -> Time.t tzresult + +val register : unit -> unit diff --git a/src/proto_009_PsFLoren/lib_protocol/delegate_storage.ml b/src/proto_009_PsFLoren/lib_protocol/delegate_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..c0f0ee99a1caa741f26f241365af2259430251f5 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/delegate_storage.ml @@ -0,0 +1,608 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type frozen_balance = { + deposit : Tez_repr.t; + fees : Tez_repr.t; + rewards : Tez_repr.t; +} + +let frozen_balance_encoding = + let open Data_encoding in + conv + (fun {deposit; fees; rewards} -> (deposit, fees, rewards)) + (fun (deposit, fees, rewards) -> {deposit; fees; rewards}) + (obj3 + (req "deposit" Tez_repr.encoding) + (req "fees" Tez_repr.encoding) + (req "rewards" Tez_repr.encoding)) + +type error += + | No_deletion of Signature.Public_key_hash.t (* `Permanent *) + | Active_delegate (* `Temporary *) + | Current_delegate (* `Temporary *) + | Empty_delegate_account of Signature.Public_key_hash.t (* `Temporary *) + | Balance_too_low_for_deposit of { + delegate : Signature.Public_key_hash.t; + deposit : Tez_repr.t; + balance : Tez_repr.t; + } + +(* `Temporary *) + +let () = + register_error_kind + `Permanent + ~id:"delegate.no_deletion" + ~title:"Forbidden delegate deletion" + ~description:"Tried to unregister a delegate" + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "Delegate deletion is forbidden (%a)" + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function No_deletion c -> Some c | _ -> None) + (fun c -> No_deletion c) ; + register_error_kind + `Temporary + ~id:"delegate.already_active" + ~title:"Delegate already active" + ~description:"Useless delegate reactivation" + ~pp:(fun ppf () -> + Format.fprintf ppf "The delegate is still active, no need to refresh it") + Data_encoding.empty + (function Active_delegate -> Some () | _ -> None) + (fun () -> Active_delegate) ; + register_error_kind + `Temporary + ~id:"delegate.unchanged" + ~title:"Unchanged delegated" + ~description:"Contract already delegated to the given delegate" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The contract is already delegated to the same delegate") + Data_encoding.empty + (function Current_delegate -> Some () | _ -> None) + (fun () -> Current_delegate) ; + register_error_kind + `Permanent + ~id:"delegate.empty_delegate_account" + ~title:"Empty delegate account" + ~description: + "Cannot register a delegate when its implicit account is empty" + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "Delegate registration is forbidden when the delegate\n\ + \ implicit account is empty (%a)" + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Empty_delegate_account c -> Some c | _ -> None) + (fun c -> Empty_delegate_account c) ; + register_error_kind + `Temporary + ~id:"delegate.balance_too_low_for_deposit" + ~title:"Balance too low for deposit" + ~description:"Cannot freeze deposit when the balance is too low" + ~pp:(fun ppf (delegate, balance, deposit) -> + Format.fprintf + ppf + "Delegate %a has a too low balance (%a) to deposit %a" + Signature.Public_key_hash.pp + delegate + Tez_repr.pp + balance + Tez_repr.pp + deposit) + Data_encoding.( + obj3 + (req "delegate" Signature.Public_key_hash.encoding) + (req "balance" Tez_repr.encoding) + (req "deposit" Tez_repr.encoding)) + (function + | Balance_too_low_for_deposit {delegate; balance; deposit} -> + Some (delegate, balance, deposit) + | _ -> + None) + (fun (delegate, balance, deposit) -> + Balance_too_low_for_deposit {delegate; balance; deposit}) + +let link c contract delegate = + Storage.Contract.Balance.get c contract + >>=? fun balance -> + Roll_storage.Delegate.add_amount c delegate balance + >>=? fun c -> + Storage.Contract.Delegated.add + (c, Contract_repr.implicit_contract delegate) + contract + >|= ok + +let unlink c contract = + Storage.Contract.Balance.get c contract + >>=? fun balance -> + Storage.Contract.Delegate.find c contract + >>=? function + | None -> + return c + | Some delegate -> + (* Removes the balance of the contract from the delegate *) + Roll_storage.Delegate.remove_amount c delegate balance + >>=? fun c -> + Storage.Contract.Delegated.remove + (c, Contract_repr.implicit_contract delegate) + contract + >|= ok + +let known c delegate = + Storage.Contract.Manager.find c (Contract_repr.implicit_contract delegate) + >>=? function + | None | Some (Manager_repr.Hash _) -> + return_false + | Some (Manager_repr.Public_key _) -> + return_true + +(* A delegate is registered if its "implicit account" delegates to itself. *) +let registered c delegate = + Storage.Contract.Delegate.find c (Contract_repr.implicit_contract delegate) + >|=? function + | Some current_delegate -> + Signature.Public_key_hash.equal delegate current_delegate + | None -> + false + +let init ctxt contract delegate = + known ctxt delegate + >>=? fun known_delegate -> + error_unless known_delegate (Roll_storage.Unregistered_delegate delegate) + >>?= fun () -> + registered ctxt delegate + >>=? fun is_registered -> + error_unless is_registered (Roll_storage.Unregistered_delegate delegate) + >>?= fun () -> + Storage.Contract.Delegate.init ctxt contract delegate + >>=? fun ctxt -> link ctxt contract delegate + +let get = Roll_storage.get_contract_delegate + +let set c contract delegate = + match delegate with + | None -> ( + let delete () = + unlink c contract + >>=? fun c -> Storage.Contract.Delegate.remove c contract >|= ok + in + match Contract_repr.is_implicit contract with + | Some pkh -> + (* check if contract is a registered delegate *) + registered c pkh + >>=? fun is_registered -> + if is_registered then fail (No_deletion pkh) else delete () + | None -> + delete () ) + | Some delegate -> + known c delegate + >>=? fun known_delegate -> + registered c delegate + >>=? fun registered_delegate -> + let self_delegation = + match Contract_repr.is_implicit contract with + | Some pkh -> + Signature.Public_key_hash.equal pkh delegate + | None -> + false + in + if (not known_delegate) || not (registered_delegate || self_delegation) + then fail (Roll_storage.Unregistered_delegate delegate) + else + Storage.Contract.Delegate.find c contract + >>=? (function + | Some current_delegate + when Signature.Public_key_hash.equal delegate current_delegate + -> + if self_delegation then + Roll_storage.Delegate.is_inactive c delegate + >>=? function + | true -> return_unit | false -> fail Active_delegate + else fail Current_delegate + | None | Some _ -> + return_unit) + >>=? fun () -> + (* check if contract is a registered delegate *) + ( match Contract_repr.is_implicit contract with + | Some pkh -> + registered c pkh + >>=? fun is_registered -> + (* allow self-delegation to re-activate *) + if (not self_delegation) && is_registered then + fail (No_deletion pkh) + else return_unit + | None -> + return_unit ) + >>=? fun () -> + Storage.Contract.Balance.mem c contract + >>= fun exists -> + error_when + (self_delegation && not exists) + (Empty_delegate_account delegate) + >>?= fun () -> + unlink c contract + >>=? fun c -> + Storage.Contract.Delegate.add c contract delegate + >>= fun c -> + link c contract delegate + >>=? fun c -> + if self_delegation then + Storage.Delegates.add c delegate + >>= fun c -> Roll_storage.Delegate.set_active c delegate + else return c + +let remove ctxt contract = unlink ctxt contract + +let delegated_contracts ctxt delegate = + let contract = Contract_repr.implicit_contract delegate in + Storage.Contract.Delegated.elements (ctxt, contract) + +let get_frozen_deposit ctxt contract cycle = + Storage.Contract.Frozen_deposits.find (ctxt, contract) cycle + >|=? Option.value ~default:Tez_repr.zero + +let credit_frozen_deposit ctxt delegate cycle amount = + let contract = Contract_repr.implicit_contract delegate in + get_frozen_deposit ctxt contract cycle + >>=? fun old_amount -> + Tez_repr.(old_amount +? amount) + >>?= fun new_amount -> + Storage.Contract.Frozen_deposits.add (ctxt, contract) cycle new_amount + >>= fun ctxt -> + Storage.Delegates_with_frozen_balance.add (ctxt, cycle) delegate >|= ok + +let freeze_deposit ctxt delegate amount = + let ({Level_repr.cycle; _} : Level_repr.t) = Level_storage.current ctxt in + Roll_storage.Delegate.set_active ctxt delegate + >>=? fun ctxt -> + let contract = Contract_repr.implicit_contract delegate in + Storage.Contract.Balance.get ctxt contract + >>=? fun balance -> + record_trace + (Balance_too_low_for_deposit {delegate; deposit = amount; balance}) + Tez_repr.(balance -? amount) + >>?= fun new_balance -> + Storage.Contract.Balance.update ctxt contract new_balance + >>=? fun ctxt -> credit_frozen_deposit ctxt delegate cycle amount + +let get_frozen_fees ctxt contract cycle = + Storage.Contract.Frozen_fees.find (ctxt, contract) cycle + >|=? Option.value ~default:Tez_repr.zero + +let credit_frozen_fees ctxt delegate cycle amount = + let contract = Contract_repr.implicit_contract delegate in + get_frozen_fees ctxt contract cycle + >>=? fun old_amount -> + Tez_repr.(old_amount +? amount) + >>?= fun new_amount -> + Storage.Contract.Frozen_fees.add (ctxt, contract) cycle new_amount + >>= fun ctxt -> + Storage.Delegates_with_frozen_balance.add (ctxt, cycle) delegate >|= ok + +let freeze_fees ctxt delegate amount = + let ({Level_repr.cycle; _} : Level_repr.t) = Level_storage.current ctxt in + Roll_storage.Delegate.add_amount ctxt delegate amount + >>=? fun ctxt -> credit_frozen_fees ctxt delegate cycle amount + +let burn_fees ctxt delegate cycle amount = + let contract = Contract_repr.implicit_contract delegate in + get_frozen_fees ctxt contract cycle + >>=? fun old_amount -> + ( match Tez_repr.(old_amount -? amount) with + | Ok new_amount -> + Roll_storage.Delegate.remove_amount ctxt delegate amount + >|=? fun ctxt -> (new_amount, ctxt) + | Error _ -> + Roll_storage.Delegate.remove_amount ctxt delegate old_amount + >|=? fun ctxt -> (Tez_repr.zero, ctxt) ) + >>=? fun (new_amount, ctxt) -> + Storage.Contract.Frozen_fees.add (ctxt, contract) cycle new_amount >|= ok + +let get_frozen_rewards ctxt contract cycle = + Storage.Contract.Frozen_rewards.find (ctxt, contract) cycle + >|=? Option.value ~default:Tez_repr.zero + +let credit_frozen_rewards ctxt delegate cycle amount = + let contract = Contract_repr.implicit_contract delegate in + get_frozen_rewards ctxt contract cycle + >>=? fun old_amount -> + Tez_repr.(old_amount +? amount) + >>?= fun new_amount -> + Storage.Contract.Frozen_rewards.add (ctxt, contract) cycle new_amount + >>= fun ctxt -> + Storage.Delegates_with_frozen_balance.add (ctxt, cycle) delegate >|= ok + +let freeze_rewards ctxt delegate amount = + let ({Level_repr.cycle; _} : Level_repr.t) = Level_storage.current ctxt in + credit_frozen_rewards ctxt delegate cycle amount + +let burn_rewards ctxt delegate cycle amount = + let contract = Contract_repr.implicit_contract delegate in + get_frozen_rewards ctxt contract cycle + >>=? fun old_amount -> + let new_amount = + match Tez_repr.(old_amount -? amount) with + | Error _ -> + Tez_repr.zero + | Ok new_amount -> + new_amount + in + Storage.Contract.Frozen_rewards.add (ctxt, contract) cycle new_amount >|= ok + +let unfreeze ctxt delegate cycle = + let contract = Contract_repr.implicit_contract delegate in + get_frozen_deposit ctxt contract cycle + >>=? fun deposit -> + get_frozen_fees ctxt contract cycle + >>=? fun fees -> + get_frozen_rewards ctxt contract cycle + >>=? fun rewards -> + Storage.Contract.Balance.get ctxt contract + >>=? fun balance -> + Tez_repr.(deposit +? fees) + >>?= fun unfrozen_amount -> + Tez_repr.(unfrozen_amount +? rewards) + >>?= fun unfrozen_amount -> + Tez_repr.(balance +? unfrozen_amount) + >>?= fun balance -> + Storage.Contract.Balance.update ctxt contract balance + >>=? fun ctxt -> + Roll_storage.Delegate.add_amount ctxt delegate rewards + >>=? fun ctxt -> + Storage.Contract.Frozen_deposits.remove (ctxt, contract) cycle + >>= fun ctxt -> + Storage.Contract.Frozen_fees.remove (ctxt, contract) cycle + >>= fun ctxt -> + Storage.Contract.Frozen_rewards.remove (ctxt, contract) cycle + >|= fun ctxt -> + ok + ( ctxt, + Receipt_repr.cleanup_balance_updates + [ (Deposits (delegate, cycle), Debited deposit, Block_application); + (Fees (delegate, cycle), Debited fees, Block_application); + (Rewards (delegate, cycle), Debited rewards, Block_application); + ( Contract (Contract_repr.implicit_contract delegate), + Credited unfrozen_amount, + Block_application ) ] ) + +let cycle_end ctxt last_cycle unrevealed = + let preserved = Constants_storage.preserved_cycles ctxt in + ( match Cycle_repr.pred last_cycle with + | None -> + return (ctxt, []) + | Some revealed_cycle -> + fold_left_s + (fun (ctxt, balance_updates) (u : Nonce_storage.unrevealed) -> + burn_fees ctxt u.delegate revealed_cycle u.fees + >>=? fun ctxt -> + burn_rewards ctxt u.delegate revealed_cycle u.rewards + >|=? fun ctxt -> + let bus = + Receipt_repr. + [ ( Fees (u.delegate, revealed_cycle), + Debited u.fees, + Block_application ); + ( Rewards (u.delegate, revealed_cycle), + Debited u.rewards, + Block_application ) ] + in + (ctxt, bus @ balance_updates)) + (ctxt, []) + unrevealed ) + >>=? fun (ctxt, balance_updates) -> + match Cycle_repr.sub last_cycle preserved with + | None -> + return (ctxt, balance_updates, []) + | Some unfrozen_cycle -> + Storage.Delegates_with_frozen_balance.fold + (ctxt, unfrozen_cycle) + ~init:(Ok (ctxt, balance_updates)) + ~f:(fun delegate acc -> + acc + >>?= fun (ctxt, bus) -> + unfreeze ctxt delegate unfrozen_cycle + >|=? fun (ctxt, balance_updates) -> (ctxt, balance_updates @ bus)) + >>=? fun (ctxt, balance_updates) -> + Storage.Delegates_with_frozen_balance.clear (ctxt, unfrozen_cycle) + >>= fun ctxt -> + Storage.Active_delegates_with_rolls.fold + ctxt + ~init:(Ok (ctxt, [])) + ~f:(fun delegate acc -> + acc + >>?= fun (ctxt, deactivated) -> + Storage.Contract.Delegate_desactivation.get + ctxt + (Contract_repr.implicit_contract delegate) + >>=? fun cycle -> + if Cycle_repr.(cycle <= last_cycle) then + Roll_storage.Delegate.set_inactive ctxt delegate + >|=? fun ctxt -> (ctxt, delegate :: deactivated) + else return (ctxt, deactivated)) + >|=? fun (ctxt, deactivated) -> (ctxt, balance_updates, deactivated) + +let punish ctxt delegate cycle = + let contract = Contract_repr.implicit_contract delegate in + get_frozen_deposit ctxt contract cycle + >>=? fun deposit -> + get_frozen_fees ctxt contract cycle + >>=? fun fees -> + get_frozen_rewards ctxt contract cycle + >>=? fun rewards -> + Roll_storage.Delegate.remove_amount ctxt delegate deposit + >>=? fun ctxt -> + Roll_storage.Delegate.remove_amount ctxt delegate fees + >>=? fun ctxt -> + (* Rewards are not accounted in the delegate's rolls yet... *) + Storage.Contract.Frozen_deposits.remove (ctxt, contract) cycle + >>= fun ctxt -> + Storage.Contract.Frozen_fees.remove (ctxt, contract) cycle + >>= fun ctxt -> + Storage.Contract.Frozen_rewards.remove (ctxt, contract) cycle + >|= fun ctxt -> ok (ctxt, {deposit; fees; rewards}) + +let has_frozen_balance ctxt delegate cycle = + let contract = Contract_repr.implicit_contract delegate in + get_frozen_deposit ctxt contract cycle + >>=? fun deposit -> + if Tez_repr.(deposit <> zero) then return_true + else + get_frozen_fees ctxt contract cycle + >>=? fun fees -> + if Tez_repr.(fees <> zero) then return_true + else + get_frozen_rewards ctxt contract cycle + >|=? fun rewards -> Tez_repr.(rewards <> zero) + +let frozen_balance_by_cycle_encoding = + let open Data_encoding in + conv + Cycle_repr.Map.bindings + (List.fold_left + (fun m (c, b) -> Cycle_repr.Map.add c b m) + Cycle_repr.Map.empty) + (list + (merge_objs + (obj1 (req "cycle" Cycle_repr.encoding)) + frozen_balance_encoding)) + +let empty_frozen_balance = + {deposit = Tez_repr.zero; fees = Tez_repr.zero; rewards = Tez_repr.zero} + +let frozen_balance_by_cycle ctxt delegate = + let contract = Contract_repr.implicit_contract delegate in + let map = Cycle_repr.Map.empty in + Storage.Contract.Frozen_deposits.fold + (ctxt, contract) + ~init:map + ~f:(fun cycle amount map -> + Lwt.return + (Cycle_repr.Map.add + cycle + {empty_frozen_balance with deposit = amount} + map)) + >>= fun map -> + Storage.Contract.Frozen_fees.fold + (ctxt, contract) + ~init:map + ~f:(fun cycle amount map -> + let balance = + match Cycle_repr.Map.find_opt cycle map with + | None -> + empty_frozen_balance + | Some balance -> + balance + in + Lwt.return (Cycle_repr.Map.add cycle {balance with fees = amount} map)) + >>= fun map -> + Storage.Contract.Frozen_rewards.fold + (ctxt, contract) + ~init:map + ~f:(fun cycle amount map -> + let balance = + match Cycle_repr.Map.find_opt cycle map with + | None -> + empty_frozen_balance + | Some balance -> + balance + in + Lwt.return (Cycle_repr.Map.add cycle {balance with rewards = amount} map)) + +let frozen_balance ctxt delegate = + let contract = Contract_repr.implicit_contract delegate in + let balance = Ok Tez_repr.zero in + Storage.Contract.Frozen_deposits.fold + (ctxt, contract) + ~init:balance + ~f:(fun _cycle amount acc -> + Lwt.return (acc >>? fun acc -> Tez_repr.(acc +? amount))) + >>= fun balance -> + Storage.Contract.Frozen_fees.fold + (ctxt, contract) + ~init:balance + ~f:(fun _cycle amount acc -> + Lwt.return (acc >>? fun acc -> Tez_repr.(acc +? amount))) + >>= fun balance -> + Storage.Contract.Frozen_rewards.fold + (ctxt, contract) + ~init:balance + ~f:(fun _cycle amount acc -> + Lwt.return (acc >>? fun acc -> Tez_repr.(acc +? amount))) + +let full_balance ctxt delegate = + let contract = Contract_repr.implicit_contract delegate in + frozen_balance ctxt delegate + >>=? fun frozen_balance -> + Storage.Contract.Balance.get ctxt contract + >>=? fun balance -> Lwt.return Tez_repr.(frozen_balance +? balance) + +let deactivated = Roll_storage.Delegate.is_inactive + +let grace_period ctxt delegate = + let contract = Contract_repr.implicit_contract delegate in + Storage.Contract.Delegate_desactivation.get ctxt contract + +let staking_balance ctxt delegate = + let token_per_rolls = Constants_storage.tokens_per_roll ctxt in + Roll_storage.count_rolls ctxt delegate + >>=? fun rolls -> + Roll_storage.get_change ctxt delegate + >>=? fun change -> + Lwt.return + ( Tez_repr.(token_per_rolls *? Int64.of_int rolls) + >>? fun balance -> Tez_repr.(balance +? change) ) + +let delegated_balance ctxt delegate = + let contract = Contract_repr.implicit_contract delegate in + staking_balance ctxt delegate + >>=? fun staking_balance -> + Storage.Contract.Balance.get ctxt contract + >>= fun self_staking_balance -> + Storage.Contract.Frozen_deposits.fold + (ctxt, contract) + ~init:self_staking_balance + ~f:(fun _cycle amount acc -> + Lwt.return (acc >>? fun acc -> Tez_repr.(acc +? amount))) + >>= fun self_staking_balance -> + Storage.Contract.Frozen_fees.fold + (ctxt, contract) + ~init:self_staking_balance + ~f:(fun _cycle amount acc -> + Lwt.return (acc >>? fun acc -> Tez_repr.(acc +? amount))) + >>=? fun self_staking_balance -> + Lwt.return Tez_repr.(staking_balance -? self_staking_balance) + +let fold = Storage.Delegates.fold + +let list = Storage.Delegates.elements diff --git a/src/proto_009_PsFLoren/lib_protocol/delegate_storage.mli b/src/proto_009_PsFLoren/lib_protocol/delegate_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..d999666ad1c117e3967e5c8a249aceb6bab8ebc8 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/delegate_storage.mli @@ -0,0 +1,176 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type frozen_balance = { + deposit : Tez_repr.t; + fees : Tez_repr.t; + rewards : Tez_repr.t; +} + +(** Allow to register a delegate when creating an account. *) +val init : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t -> + Raw_context.t tzresult Lwt.t + +(** Cleanup delegation when deleting a contract. *) +val remove : Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t + +(** Reading the current delegate of a contract. *) +val get : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t option tzresult Lwt.t + +val registered : + Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + +(** Updating the delegate of a contract. + + When calling this function on an "implicit contract" and setting + the delegate to the contract manager registers it as a delegate. One + cannot unregister a delegate for now. The associate contract is now + 'undeletable'. *) +val set : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t option -> + Raw_context.t tzresult Lwt.t + +type error += + | No_deletion of Signature.Public_key_hash.t (* `Permanent *) + | Active_delegate (* `Temporary *) + | Current_delegate (* `Temporary *) + | Empty_delegate_account of Signature.Public_key_hash.t (* `Temporary *) + | Balance_too_low_for_deposit of { + delegate : Signature.Public_key_hash.t; + deposit : Tez_repr.t; + balance : Tez_repr.t; + } + +(* `Temporary *) + +(** Iterate on all registered delegates. *) +val fold : + Raw_context.t -> + init:'a -> + f:(Signature.Public_key_hash.t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + +(** List all registered delegates. *) +val list : Raw_context.t -> Signature.Public_key_hash.t list Lwt.t + +(** Various functions to 'freeze' tokens. A frozen 'deposit' keeps its + associated rolls. When frozen, 'fees' may trigger new rolls + allocation. Rewards won't trigger new rolls allocation until + unfrozen. *) +val freeze_deposit : + Raw_context.t -> + Signature.Public_key_hash.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val freeze_fees : + Raw_context.t -> + Signature.Public_key_hash.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val freeze_rewards : + Raw_context.t -> + Signature.Public_key_hash.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +(** Trigger the context maintenance at the end of cycle 'n', i.e.: + unfreeze deposit/fees/rewards from 'n - preserved_cycle' ; punish the + provided unrevealed seeds (typically seed from cycle 'n - 1'). + Returns a list of account with the amount that was unfrozen for each + and the list of deactivated delegates. *) +val cycle_end : + Raw_context.t -> + Cycle_repr.t -> + Nonce_storage.unrevealed list -> + ( Raw_context.t + * Receipt_repr.balance_updates + * Signature.Public_key_hash.t list ) + tzresult + Lwt.t + +(** Burn all then frozen deposit/fees/rewards for a delegate at a given + cycle. Returns the burned amounts. *) +val punish : + Raw_context.t -> + Signature.Public_key_hash.t -> + Cycle_repr.t -> + (Raw_context.t * frozen_balance) tzresult Lwt.t + +(** Has the given key some frozen tokens in its implicit contract? *) +val has_frozen_balance : + Raw_context.t -> + Signature.Public_key_hash.t -> + Cycle_repr.t -> + bool tzresult Lwt.t + +(** Returns the amount of frozen deposit, fees and rewards associated + to a given delegate. *) +val frozen_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + +val frozen_balance_encoding : frozen_balance Data_encoding.t + +val frozen_balance_by_cycle_encoding : + frozen_balance Cycle_repr.Map.t Data_encoding.t + +(** Returns the amount of frozen deposit, fees and rewards associated + to a given delegate, indexed by the cycle by which at the end the + balance will be unfrozen. *) +val frozen_balance_by_cycle : + Raw_context.t -> + Signature.Public_key_hash.t -> + frozen_balance Cycle_repr.Map.t Lwt.t + +(** Returns the full 'balance' of the implicit contract associated to + a given key, i.e. the sum of the spendable balance and of the + frozen balance. *) +val full_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + +val staking_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + +(** Returns the list of contracts (implicit or originated) that delegated towards a given delegate *) +val delegated_contracts : + Raw_context.t -> Signature.Public_key_hash.t -> Contract_repr.t list Lwt.t + +val delegated_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + +val deactivated : + Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + +val grace_period : + Raw_context.t -> Signature.Public_key_hash.t -> Cycle_repr.t tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/dune b/src/proto_009_PsFLoren/lib_protocol/dune new file mode 120000 index 0000000000000000000000000000000000000000..235c3740ecfc863528ec6353bbff8ea81e3f22e2 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/dune @@ -0,0 +1 @@ +../../lib_protocol_compiler/dune_protocol \ No newline at end of file diff --git a/src/proto_009_PsFLoren/lib_protocol/dune-project b/src/proto_009_PsFLoren/lib_protocol/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..170737ae3e8f2fb8b81c22505aa8b1ba8f8b6339 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-embedded-protocol-009-PsFLoren) diff --git a/src/proto_009_PsFLoren/lib_protocol/dune.inc b/src/proto_009_PsFLoren/lib_protocol/dune.inc new file mode 100644 index 0000000000000000000000000000000000000000..047b6507ff1da45d66185156bd2d21cac945870a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/dune.inc @@ -0,0 +1,517 @@ + + +; +; /!\ /!\ Do not modify this file /!\ /!\ +; +; but the original template in `tezos-protocol-compiler` +; + + +(rule + (targets environment.ml) + (action + (write-file %{targets} + "module Name = struct let name = \"009-PsFLoren\" end +include Tezos_protocol_environment.MakeV2(Name)() +module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end +"))) + +(rule + (targets registerer.ml) + (deps + misc.mli misc.ml + storage_description.mli storage_description.ml + state_hash.mli state_hash.ml + nonce_hash.mli nonce_hash.ml + script_expr_hash.mli script_expr_hash.ml + contract_hash.mli contract_hash.ml + blinded_public_key_hash.mli blinded_public_key_hash.ml + tez_repr.mli tez_repr.ml + period_repr.mli period_repr.ml + time_repr.mli time_repr.ml + fixed_point_repr.mli fixed_point_repr.ml + saturation_repr.mli saturation_repr.ml + gas_limit_repr.mli gas_limit_repr.ml + constants_repr.mli constants_repr.ml + fitness_repr.mli fitness_repr.ml + raw_level_repr.mli raw_level_repr.ml + cycle_repr.mli cycle_repr.ml + level_repr.mli level_repr.ml + seed_repr.mli seed_repr.ml + voting_period_repr.mli voting_period_repr.ml + script_int_repr.mli script_int_repr.ml + script_timestamp_repr.mli script_timestamp_repr.ml + michelson_v1_primitives.mli michelson_v1_primitives.ml + script_repr.mli script_repr.ml + contract_repr.mli contract_repr.ml + roll_repr.mli roll_repr.ml + vote_repr.mli vote_repr.ml + block_header_repr.mli block_header_repr.ml + operation_repr.mli operation_repr.ml + manager_repr.mli manager_repr.ml + commitment_repr.mli commitment_repr.ml + parameters_repr.mli parameters_repr.ml + sapling_repr.ml + lazy_storage_kind.mli lazy_storage_kind.ml + receipt_repr.mli receipt_repr.ml + raw_context_intf.ml + raw_context.mli raw_context.ml + storage_costs.mli storage_costs.ml + storage_sigs.ml + storage_functors.mli storage_functors.ml + storage.mli storage.ml + constants_storage.mli constants_storage.ml + level_storage.mli level_storage.ml + nonce_storage.mli nonce_storage.ml + seed_storage.mli seed_storage.ml + roll_storage.mli roll_storage.ml + delegate_storage.mli delegate_storage.ml + sapling_storage.ml + lazy_storage_diff.mli lazy_storage_diff.ml + contract_storage.mli contract_storage.ml + bootstrap_storage.mli bootstrap_storage.ml + fitness_storage.mli fitness_storage.ml + voting_period_storage.mli voting_period_storage.ml + vote_storage.mli vote_storage.ml + commitment_storage.mli commitment_storage.ml + init_storage.mli init_storage.ml + fees_storage.mli fees_storage.ml + sapling_validator.ml + alpha_context.mli alpha_context.ml + script_typed_ir.ml + script_tc_errors.ml + michelson_v1_gas.mli michelson_v1_gas.ml + script_ir_annot.mli script_ir_annot.ml + script_ir_translator.mli script_ir_translator.ml + script_tc_errors_registration.mli script_tc_errors_registration.ml + script_interpreter.mli script_interpreter.ml + baking.mli baking.ml + amendment.mli amendment.ml + apply_results.mli apply_results.ml + apply.mli apply.ml + services_registration.mli services_registration.ml + constants_services.mli constants_services.ml + sapling_services.ml + contract_services.mli contract_services.ml + delegate_services.mli delegate_services.ml + helpers_services.mli helpers_services.ml + voting_services.mli voting_services.ml + alpha_services.mli alpha_services.ml + main.mli main.ml + (:src_dir TEZOS_PROTOCOL)) + (action + (with-stdout-to %{targets} + (chdir %{workspace_root} (run %{bin:tezos-embedded-protocol-packer} "%{src_dir}" "009_PsFLoren"))))) + +(rule + (targets functor.ml) + (deps + misc.mli misc.ml + storage_description.mli storage_description.ml + state_hash.mli state_hash.ml + nonce_hash.mli nonce_hash.ml + script_expr_hash.mli script_expr_hash.ml + contract_hash.mli contract_hash.ml + blinded_public_key_hash.mli blinded_public_key_hash.ml + tez_repr.mli tez_repr.ml + period_repr.mli period_repr.ml + time_repr.mli time_repr.ml + fixed_point_repr.mli fixed_point_repr.ml + saturation_repr.mli saturation_repr.ml + gas_limit_repr.mli gas_limit_repr.ml + constants_repr.mli constants_repr.ml + fitness_repr.mli fitness_repr.ml + raw_level_repr.mli raw_level_repr.ml + cycle_repr.mli cycle_repr.ml + level_repr.mli level_repr.ml + seed_repr.mli seed_repr.ml + voting_period_repr.mli voting_period_repr.ml + script_int_repr.mli script_int_repr.ml + script_timestamp_repr.mli script_timestamp_repr.ml + michelson_v1_primitives.mli michelson_v1_primitives.ml + script_repr.mli script_repr.ml + contract_repr.mli contract_repr.ml + roll_repr.mli roll_repr.ml + vote_repr.mli vote_repr.ml + block_header_repr.mli block_header_repr.ml + operation_repr.mli operation_repr.ml + manager_repr.mli manager_repr.ml + commitment_repr.mli commitment_repr.ml + parameters_repr.mli parameters_repr.ml + sapling_repr.ml + lazy_storage_kind.mli lazy_storage_kind.ml + receipt_repr.mli receipt_repr.ml + raw_context_intf.ml + raw_context.mli raw_context.ml + storage_costs.mli storage_costs.ml + storage_sigs.ml + storage_functors.mli storage_functors.ml + storage.mli storage.ml + constants_storage.mli constants_storage.ml + level_storage.mli level_storage.ml + nonce_storage.mli nonce_storage.ml + seed_storage.mli seed_storage.ml + roll_storage.mli roll_storage.ml + delegate_storage.mli delegate_storage.ml + sapling_storage.ml + lazy_storage_diff.mli lazy_storage_diff.ml + contract_storage.mli contract_storage.ml + bootstrap_storage.mli bootstrap_storage.ml + fitness_storage.mli fitness_storage.ml + voting_period_storage.mli voting_period_storage.ml + vote_storage.mli vote_storage.ml + commitment_storage.mli commitment_storage.ml + init_storage.mli init_storage.ml + fees_storage.mli fees_storage.ml + sapling_validator.ml + alpha_context.mli alpha_context.ml + script_typed_ir.ml + script_tc_errors.ml + michelson_v1_gas.mli michelson_v1_gas.ml + script_ir_annot.mli script_ir_annot.ml + script_ir_translator.mli script_ir_translator.ml + script_tc_errors_registration.mli script_tc_errors_registration.ml + script_interpreter.mli script_interpreter.ml + baking.mli baking.ml + amendment.mli amendment.ml + apply_results.mli apply_results.ml + apply.mli apply.ml + services_registration.mli services_registration.ml + constants_services.mli constants_services.ml + sapling_services.ml + contract_services.mli contract_services.ml + delegate_services.mli delegate_services.ml + helpers_services.mli helpers_services.ml + voting_services.mli voting_services.ml + alpha_services.mli alpha_services.ml + main.mli main.ml + (:src_dir TEZOS_PROTOCOL)) + (action (with-stdout-to %{targets} + (chdir %{workspace_root} + (run %{bin:tezos-protocol-compiler.tezos-protocol-packer} %{src_dir}))))) + +(rule + (targets protocol.ml) + (deps + misc.mli misc.ml + storage_description.mli storage_description.ml + state_hash.mli state_hash.ml + nonce_hash.mli nonce_hash.ml + script_expr_hash.mli script_expr_hash.ml + contract_hash.mli contract_hash.ml + blinded_public_key_hash.mli blinded_public_key_hash.ml + tez_repr.mli tez_repr.ml + period_repr.mli period_repr.ml + time_repr.mli time_repr.ml + fixed_point_repr.mli fixed_point_repr.ml + saturation_repr.mli saturation_repr.ml + gas_limit_repr.mli gas_limit_repr.ml + constants_repr.mli constants_repr.ml + fitness_repr.mli fitness_repr.ml + raw_level_repr.mli raw_level_repr.ml + cycle_repr.mli cycle_repr.ml + level_repr.mli level_repr.ml + seed_repr.mli seed_repr.ml + voting_period_repr.mli voting_period_repr.ml + script_int_repr.mli script_int_repr.ml + script_timestamp_repr.mli script_timestamp_repr.ml + michelson_v1_primitives.mli michelson_v1_primitives.ml + script_repr.mli script_repr.ml + contract_repr.mli contract_repr.ml + roll_repr.mli roll_repr.ml + vote_repr.mli vote_repr.ml + block_header_repr.mli block_header_repr.ml + operation_repr.mli operation_repr.ml + manager_repr.mli manager_repr.ml + commitment_repr.mli commitment_repr.ml + parameters_repr.mli parameters_repr.ml + sapling_repr.ml + lazy_storage_kind.mli lazy_storage_kind.ml + receipt_repr.mli receipt_repr.ml + raw_context_intf.ml + raw_context.mli raw_context.ml + storage_costs.mli storage_costs.ml + storage_sigs.ml + storage_functors.mli storage_functors.ml + storage.mli storage.ml + constants_storage.mli constants_storage.ml + level_storage.mli level_storage.ml + nonce_storage.mli nonce_storage.ml + seed_storage.mli seed_storage.ml + roll_storage.mli roll_storage.ml + delegate_storage.mli delegate_storage.ml + sapling_storage.ml + lazy_storage_diff.mli lazy_storage_diff.ml + contract_storage.mli contract_storage.ml + bootstrap_storage.mli bootstrap_storage.ml + fitness_storage.mli fitness_storage.ml + voting_period_storage.mli voting_period_storage.ml + vote_storage.mli vote_storage.ml + commitment_storage.mli commitment_storage.ml + init_storage.mli init_storage.ml + fees_storage.mli fees_storage.ml + sapling_validator.ml + alpha_context.mli alpha_context.ml + script_typed_ir.ml + script_tc_errors.ml + michelson_v1_gas.mli michelson_v1_gas.ml + script_ir_annot.mli script_ir_annot.ml + script_ir_translator.mli script_ir_translator.ml + script_tc_errors_registration.mli script_tc_errors_registration.ml + script_interpreter.mli script_interpreter.ml + baking.mli baking.ml + amendment.mli amendment.ml + apply_results.mli apply_results.ml + apply.mli apply.ml + services_registration.mli services_registration.ml + constants_services.mli constants_services.ml + sapling_services.ml + contract_services.mli contract_services.ml + delegate_services.mli delegate_services.ml + helpers_services.mli helpers_services.ml + voting_services.mli voting_services.ml + alpha_services.mli alpha_services.ml + main.mli main.ml) + (action + (write-file %{targets} + "module Environment = Tezos_protocol_environment_009_PsFLoren.Environment +let hash = Tezos_crypto.Protocol_hash.of_b58check_exn \"PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i\" +let name = Environment.Name.name +include Tezos_raw_protocol_009_PsFLoren +include Tezos_raw_protocol_009_PsFLoren.Main +"))) + +(library + (name tezos_protocol_environment_009_PsFLoren) + (public_name tezos-protocol-009-PsFLoren.environment) + (library_flags (:standard -linkall)) + (libraries tezos-protocol-environment) + (modules Environment)) + +(library + (name tezos_raw_protocol_009_PsFLoren) + (public_name tezos-protocol-009-PsFLoren.raw) + (libraries tezos_protocol_environment_009_PsFLoren) + (library_flags (:standard -linkall)) + (flags (:standard -nopervasives -nostdlib + -w +a-4-6-7-9-29-32-40..42-44-45-48-60-67 + -warn-error +a + -open Tezos_protocol_environment_009_PsFLoren__Environment + -open Pervasives + -open Error_monad)) + (modules + Misc + Storage_description + State_hash + Nonce_hash + Script_expr_hash + Contract_hash + Blinded_public_key_hash + Tez_repr + Period_repr + Time_repr + Fixed_point_repr + Saturation_repr + Gas_limit_repr + Constants_repr + Fitness_repr + Raw_level_repr + Cycle_repr + Level_repr + Seed_repr + Voting_period_repr + Script_int_repr + Script_timestamp_repr + Michelson_v1_primitives + Script_repr + Contract_repr + Roll_repr + Vote_repr + Block_header_repr + Operation_repr + Manager_repr + Commitment_repr + Parameters_repr + Sapling_repr + Lazy_storage_kind + Receipt_repr + Raw_context_intf + Raw_context + Storage_costs + Storage_sigs + Storage_functors + Storage + Constants_storage + Level_storage + Nonce_storage + Seed_storage + Roll_storage + Delegate_storage + Sapling_storage + Lazy_storage_diff + Contract_storage + Bootstrap_storage + Fitness_storage + Voting_period_storage + Vote_storage + Commitment_storage + Init_storage + Fees_storage + Sapling_validator + Alpha_context + Script_typed_ir + Script_tc_errors + Michelson_v1_gas + Script_ir_annot + Script_ir_translator + Script_tc_errors_registration + Script_interpreter + Baking + Amendment + Apply_results + Apply + Services_registration + Constants_services + Sapling_services + Contract_services + Delegate_services + Helpers_services + Voting_services + Alpha_services + Main)) + +(install + (section lib) + (package tezos-protocol-009-PsFLoren) + (files (TEZOS_PROTOCOL as raw/TEZOS_PROTOCOL))) + +(library + (name tezos_protocol_009_PsFLoren) + (public_name tezos-protocol-009-PsFLoren) + (libraries + tezos-protocol-environment + tezos-protocol-environment-sigs + tezos_raw_protocol_009_PsFLoren) + (flags -w "+a-4-6-7-9-29-40..42-44-45-48-60-67" + -warn-error "+a" + -nopervasives) + (modules Protocol)) + +(library + (name tezos_protocol_009_PsFLoren_functor) + (public_name tezos-protocol-functor-009-PsFLoren) + (libraries + tezos-protocol-environment + tezos-protocol-environment-sigs + tezos-protocol-009-PsFLoren.raw) + (flags -w "+a-4-6-7-9-29-40..42-44-45-48-60-67" + -warn-error "+a" + -nopervasives) + (modules Functor)) + +(library + (name tezos_embedded_protocol_009_PsFLoren) + (public_name tezos-embedded-protocol-009-PsFLoren) + (library_flags (:standard -linkall)) + (libraries tezos-protocol-009-PsFLoren + tezos-protocol-updater + tezos-protocol-environment) + (flags (:standard -w +a-4-6-7-9-29-32-40..42-44-45-48-60-67 + -warn-error +a)) + (modules Registerer)) + +(rule + (alias runtest_compile_protocol) + (deps + misc.mli misc.ml + storage_description.mli storage_description.ml + state_hash.mli state_hash.ml + nonce_hash.mli nonce_hash.ml + script_expr_hash.mli script_expr_hash.ml + contract_hash.mli contract_hash.ml + blinded_public_key_hash.mli blinded_public_key_hash.ml + tez_repr.mli tez_repr.ml + period_repr.mli period_repr.ml + time_repr.mli time_repr.ml + fixed_point_repr.mli fixed_point_repr.ml + saturation_repr.mli saturation_repr.ml + gas_limit_repr.mli gas_limit_repr.ml + constants_repr.mli constants_repr.ml + fitness_repr.mli fitness_repr.ml + raw_level_repr.mli raw_level_repr.ml + cycle_repr.mli cycle_repr.ml + level_repr.mli level_repr.ml + seed_repr.mli seed_repr.ml + voting_period_repr.mli voting_period_repr.ml + script_int_repr.mli script_int_repr.ml + script_timestamp_repr.mli script_timestamp_repr.ml + michelson_v1_primitives.mli michelson_v1_primitives.ml + script_repr.mli script_repr.ml + contract_repr.mli contract_repr.ml + roll_repr.mli roll_repr.ml + vote_repr.mli vote_repr.ml + block_header_repr.mli block_header_repr.ml + operation_repr.mli operation_repr.ml + manager_repr.mli manager_repr.ml + commitment_repr.mli commitment_repr.ml + parameters_repr.mli parameters_repr.ml + sapling_repr.ml + lazy_storage_kind.mli lazy_storage_kind.ml + receipt_repr.mli receipt_repr.ml + raw_context_intf.ml + raw_context.mli raw_context.ml + storage_costs.mli storage_costs.ml + storage_sigs.ml + storage_functors.mli storage_functors.ml + storage.mli storage.ml + constants_storage.mli constants_storage.ml + level_storage.mli level_storage.ml + nonce_storage.mli nonce_storage.ml + seed_storage.mli seed_storage.ml + roll_storage.mli roll_storage.ml + delegate_storage.mli delegate_storage.ml + sapling_storage.ml + lazy_storage_diff.mli lazy_storage_diff.ml + contract_storage.mli contract_storage.ml + bootstrap_storage.mli bootstrap_storage.ml + fitness_storage.mli fitness_storage.ml + voting_period_storage.mli voting_period_storage.ml + vote_storage.mli vote_storage.ml + commitment_storage.mli commitment_storage.ml + init_storage.mli init_storage.ml + fees_storage.mli fees_storage.ml + sapling_validator.ml + alpha_context.mli alpha_context.ml + script_typed_ir.ml + script_tc_errors.ml + michelson_v1_gas.mli michelson_v1_gas.ml + script_ir_annot.mli script_ir_annot.ml + script_ir_translator.mli script_ir_translator.ml + script_tc_errors_registration.mli script_tc_errors_registration.ml + script_interpreter.mli script_interpreter.ml + baking.mli baking.ml + amendment.mli amendment.ml + apply_results.mli apply_results.ml + apply.mli apply.ml + services_registration.mli services_registration.ml + constants_services.mli constants_services.ml + sapling_services.ml + contract_services.mli contract_services.ml + delegate_services.mli delegate_services.ml + helpers_services.mli helpers_services.ml + voting_services.mli voting_services.ml + alpha_services.mli alpha_services.ml + main.mli main.ml + (:src_dir TEZOS_PROTOCOL)) + (action (run %{bin:tezos-protocol-compiler} .))) + +(rule + (alias runtest_sandbox) + (deps .tezos_protocol_009_PsFLoren.objs/native/tezos_protocol_009_PsFLoren.cmx) + (action (progn))) + +(rule + (alias runtest) + (package tezos-protocol-009-PsFLoren) + (deps (alias runtest_sandbox)) + (action (progn))) diff --git a/src/proto_009_PsFLoren/lib_protocol/fees_storage.ml b/src/proto_009_PsFLoren/lib_protocol/fees_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..ddd82707c321e9697eda35863457b0354a79506b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/fees_storage.ml @@ -0,0 +1,121 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Cannot_pay_storage_fee (* `Temporary *) + +type error += Operation_quota_exceeded (* `Temporary *) + +type error += Storage_limit_too_high (* `Permanent *) + +let () = + let open Data_encoding in + register_error_kind + `Temporary + ~id:"contract.cannot_pay_storage_fee" + ~title:"Cannot pay storage fee" + ~description:"The storage fee is higher than the contract balance" + ~pp:(fun ppf () -> Format.fprintf ppf "Cannot pay storage storage fee") + Data_encoding.empty + (function Cannot_pay_storage_fee -> Some () | _ -> None) + (fun () -> Cannot_pay_storage_fee) ; + register_error_kind + `Temporary + ~id:"storage_exhausted.operation" + ~title:"Storage quota exceeded for the operation" + ~description: + "A script or one of its callee wrote more bytes than the operation said \ + it would" + Data_encoding.empty + (function Operation_quota_exceeded -> Some () | _ -> None) + (fun () -> Operation_quota_exceeded) ; + register_error_kind + `Permanent + ~id:"storage_limit_too_high" + ~title:"Storage limit out of protocol hard bounds" + ~description:"A transaction tried to exceed the hard limit on storage" + empty + (function Storage_limit_too_high -> Some () | _ -> None) + (fun () -> Storage_limit_too_high) + +let origination_burn c = + let origination_size = Constants_storage.origination_size c in + let cost_per_byte = Constants_storage.cost_per_byte c in + (* the origination burn, measured in bytes *) + Tez_repr.(cost_per_byte *? Int64.of_int origination_size) + >|? fun to_be_paid -> + (Raw_context.update_allocated_contracts_count c, to_be_paid) + +let record_paid_storage_space c contract = + Contract_storage.used_storage_space c contract + >>=? fun size -> + Contract_storage.set_paid_storage_space_and_return_fees_to_pay + c + contract + size + >>=? fun (to_be_paid, c) -> + let c = Raw_context.update_storage_space_to_pay c to_be_paid in + let cost_per_byte = Constants_storage.cost_per_byte c in + Lwt.return + ( Tez_repr.(cost_per_byte *? Z.to_int64 to_be_paid) + >|? fun to_burn -> (c, size, to_be_paid, to_burn) ) + +let burn_storage_fees c ~storage_limit ~payer = + let origination_size = Constants_storage.origination_size c in + let (c, storage_space_to_pay, allocated_contracts) = + Raw_context.clear_storage_space_to_pay c + in + let storage_space_for_allocated_contracts = + Z.mul (Z.of_int allocated_contracts) (Z.of_int origination_size) + in + let consumed = + Z.add storage_space_to_pay storage_space_for_allocated_contracts + in + let remaining = Z.sub storage_limit consumed in + if Compare.Z.(remaining < Z.zero) then fail Operation_quota_exceeded + else + let cost_per_byte = Constants_storage.cost_per_byte c in + Tez_repr.(cost_per_byte *? Z.to_int64 consumed) + >>?= fun to_burn -> + (* Burning the fees... *) + if Tez_repr.(to_burn = Tez_repr.zero) then + (* If the payer was was deleted by transferring all its balance, and no space was used, + burning zero would fail *) + return c + else + trace + Cannot_pay_storage_fee + ( Contract_storage.must_exist c payer + >>=? fun () -> Contract_storage.spend c payer to_burn ) + +let check_storage_limit c ~storage_limit = + if + Compare.Z.( + storage_limit + > (Raw_context.constants c).hard_storage_limit_per_operation) + || Compare.Z.(storage_limit < Z.zero) + then error Storage_limit_too_high + else ok_unit + +let start_counting_storage_fees c = Raw_context.init_storage_space_to_pay c diff --git a/src/proto_009_PsFLoren/lib_protocol/fees_storage.mli b/src/proto_009_PsFLoren/lib_protocol/fees_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..8e6a417c63932313b8bd0883666726b3ce43527e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/fees_storage.mli @@ -0,0 +1,49 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Cannot_pay_storage_fee (* `Temporary *) + +type error += Operation_quota_exceeded (* `Temporary *) + +type error += Storage_limit_too_high (* `Permanent *) + +(** Does not burn, only adds the burn to storage space to be paid *) +val origination_burn : Raw_context.t -> (Raw_context.t * Tez_repr.t) tzresult + +(** The returned Tez quantity is for logging purpose only *) +val record_paid_storage_space : + Raw_context.t -> + Contract_repr.t -> + (Raw_context.t * Z.t * Z.t * Tez_repr.t) tzresult Lwt.t + +val check_storage_limit : Raw_context.t -> storage_limit:Z.t -> unit tzresult + +val start_counting_storage_fees : Raw_context.t -> Raw_context.t + +val burn_storage_fees : + Raw_context.t -> + storage_limit:Z.t -> + payer:Contract_repr.t -> + Raw_context.t tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/fitness_repr.ml b/src/proto_009_PsFLoren/lib_protocol/fitness_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..cbcb5d1cd2f413dadea702308e7c9a938098eb42 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/fitness_repr.ml @@ -0,0 +1,62 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Invalid_fitness (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"invalid_fitness" + ~title:"Invalid fitness" + ~description:"Fitness representation should be exactly 8 bytes long." + ~pp:(fun ppf () -> Format.fprintf ppf "Invalid fitness") + Data_encoding.empty + (function Invalid_fitness -> Some () | _ -> None) + (fun () -> Invalid_fitness) + +let int64_to_bytes i = + let b = Bytes.make 8 '0' in + TzEndian.set_int64 b 0 i ; b + +let int64_of_bytes b = + if Compare.Int.(Bytes.length b <> 8) then error Invalid_fitness + else ok (TzEndian.get_int64 b 0) + +let from_int64 fitness = + [Bytes.of_string Constants_repr.version_number; int64_to_bytes fitness] + +let to_int64 = function + | [version; fitness] + when Compare.String.( + Bytes.to_string version = Constants_repr.version_number) -> + int64_of_bytes fitness + | [version; _fitness (* ignored since higher version takes priority *)] + when Compare.String.( + Bytes.to_string version = Constants_repr.version_number_004) -> + ok 0L + | [] -> + ok 0L + | _ -> + error Invalid_fitness diff --git a/src/proto_009_PsFLoren/lib_protocol/fitness_repr.mli b/src/proto_009_PsFLoren/lib_protocol/fitness_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..1636fae707e98f89c4ff814b988e527e46af4120 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/fitness_repr.mli @@ -0,0 +1,29 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val from_int64 : int64 -> bytes list + +val to_int64 : bytes list -> (int64, error trace) result diff --git a/src/proto_009_PsFLoren/lib_protocol/fitness_storage.ml b/src/proto_009_PsFLoren/lib_protocol/fitness_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..26d1478fc1fd147354fd91b35fe9502bcee8485a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/fitness_storage.ml @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let current = Raw_context.current_fitness + +let increase ctxt = + let fitness = current ctxt in + Raw_context.set_current_fitness ctxt (Int64.succ fitness) diff --git a/src/proto_009_PsFLoren/lib_protocol/fitness_storage.mli b/src/proto_009_PsFLoren/lib_protocol/fitness_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..c9844d2c9b1f96ad378b92aea9c6f6de1a191b71 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/fitness_storage.mli @@ -0,0 +1,29 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val current : Raw_context.t -> Int64.t + +val increase : Raw_context.t -> Raw_context.t diff --git a/src/proto_009_PsFLoren/lib_protocol/fixed_point_repr.ml b/src/proto_009_PsFLoren/lib_protocol/fixed_point_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..77ed0e743ddbfd010cd167670e3b7dfd86c1ea4a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/fixed_point_repr.ml @@ -0,0 +1,92 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type fp_tag (* Tag for fixed point computations *) + +type integral_tag (* Tag for integral computations *) + +module type Safe = sig + type 'a t + + type fp = fp_tag t + + type integral = integral_tag t + + val integral_exn : Z.t -> integral + + val integral_of_int_exn : int -> integral + + val integral_to_z : integral -> Z.t + + val zero : 'a t + + val add : 'a t -> 'a t -> 'a t + + val sub : 'a t -> 'a t -> 'a t + + val ceil : fp -> integral + + val floor : fp -> integral + + val fp : 'a t -> fp + + val ( = ) : 'a t -> 'b t -> bool + + val ( <> ) : 'a t -> 'b t -> bool + + val ( < ) : 'a t -> 'b t -> bool + + val ( <= ) : 'a t -> 'b t -> bool + + val ( >= ) : 'a t -> 'b t -> bool + + val ( > ) : 'a t -> 'b t -> bool + + val compare : 'a t -> 'b t -> int + + val equal : 'a t -> 'b t -> bool + + val max : 'a t -> 'a t -> 'a t + + val min : 'a t -> 'a t -> 'a t + + val pp : Format.formatter -> 'a t -> unit + + val pp_integral : Format.formatter -> integral -> unit + + val n_fp_encoding : fp Data_encoding.t + + val n_integral_encoding : integral Data_encoding.t + + val z_fp_encoding : fp Data_encoding.t + + val z_integral_encoding : integral Data_encoding.t +end + +module type Full = sig + include Safe + + val unsafe_fp : Z.t -> fp +end diff --git a/src/proto_009_PsFLoren/lib_protocol/fixed_point_repr.mli b/src/proto_009_PsFLoren/lib_protocol/fixed_point_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..77ed0e743ddbfd010cd167670e3b7dfd86c1ea4a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/fixed_point_repr.mli @@ -0,0 +1,92 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type fp_tag (* Tag for fixed point computations *) + +type integral_tag (* Tag for integral computations *) + +module type Safe = sig + type 'a t + + type fp = fp_tag t + + type integral = integral_tag t + + val integral_exn : Z.t -> integral + + val integral_of_int_exn : int -> integral + + val integral_to_z : integral -> Z.t + + val zero : 'a t + + val add : 'a t -> 'a t -> 'a t + + val sub : 'a t -> 'a t -> 'a t + + val ceil : fp -> integral + + val floor : fp -> integral + + val fp : 'a t -> fp + + val ( = ) : 'a t -> 'b t -> bool + + val ( <> ) : 'a t -> 'b t -> bool + + val ( < ) : 'a t -> 'b t -> bool + + val ( <= ) : 'a t -> 'b t -> bool + + val ( >= ) : 'a t -> 'b t -> bool + + val ( > ) : 'a t -> 'b t -> bool + + val compare : 'a t -> 'b t -> int + + val equal : 'a t -> 'b t -> bool + + val max : 'a t -> 'a t -> 'a t + + val min : 'a t -> 'a t -> 'a t + + val pp : Format.formatter -> 'a t -> unit + + val pp_integral : Format.formatter -> integral -> unit + + val n_fp_encoding : fp Data_encoding.t + + val n_integral_encoding : integral Data_encoding.t + + val z_fp_encoding : fp Data_encoding.t + + val z_integral_encoding : integral Data_encoding.t +end + +module type Full = sig + include Safe + + val unsafe_fp : Z.t -> fp +end diff --git a/src/proto_009_PsFLoren/lib_protocol/gas_limit_repr.ml b/src/proto_009_PsFLoren/lib_protocol/gas_limit_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..406d62d1a2456ec1f04d631092362cfe1aab01ce --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/gas_limit_repr.ml @@ -0,0 +1,208 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let decimals = 3 + +type fp_tag + +type integral_tag + +module S = Saturation_repr + +let scaling_factor = S.mul_safe_of_int_exn 1000 + +module Arith = struct + type 'a t = S.may_saturate S.t + + type fp = fp_tag t + + type integral = integral_tag t + + let scaling_factor = scaling_factor + + let sub = S.sub + + let add = S.add + + let zero = S.zero + + let min = S.min + + let max = S.max + + let compare = S.compare + + let ( < ) = S.( < ) + + let ( <> ) = S.( <> ) + + let ( > ) = S.( > ) + + let ( <= ) = S.( <= ) + + let ( >= ) = S.( >= ) + + let ( = ) = S.( = ) + + let equal = S.equal + + let of_int_opt = S.of_int_opt + + let fatally_saturated_int i = + failwith (string_of_int i ^ " should not be saturated.") + + let fatally_saturated_z z = + failwith (Z.to_string z ^ " should not be saturated.") + + let integral_of_int_exn i = + S.( + match of_int_opt i with + | None -> + fatally_saturated_int i + | Some i' -> + let r = scale_fast scaling_factor i' in + if r = saturated then fatally_saturated_int i else r) + + let integral_exn z = + match Z.to_int z with + | i -> + integral_of_int_exn i + | exception Z.Overflow -> + fatally_saturated_z z + + let integral_to_z (i : integral) : Z.t = S.(to_z (ediv i scaling_factor)) + + let ceil x = + let r = S.erem x scaling_factor in + if r = zero then x else add x (sub scaling_factor r) + + let floor x = sub x (S.erem x scaling_factor) + + let fp x = x + + let pp fmtr fp = + let q = S.(ediv fp scaling_factor |> to_int) in + let r = S.(erem fp scaling_factor |> to_int) in + if Compare.Int.(r = 0) then Format.fprintf fmtr "%d" q + else Format.fprintf fmtr "%d.%0*d" q decimals r + + let pp_integral = pp + + let n_fp_encoding : fp Data_encoding.t = S.n_encoding + + let z_fp_encoding : fp Data_encoding.t = S.z_encoding + + let n_integral_encoding : integral Data_encoding.t = + Data_encoding.conv integral_to_z integral_exn Data_encoding.n + + let z_integral_encoding : integral Data_encoding.t = + Data_encoding.conv integral_to_z integral_exn Data_encoding.z + + let unsafe_fp x = + match of_int_opt (Z.to_int x) with + | Some int -> + int + | None -> + fatally_saturated_z x + + let sub_opt = S.sub_opt +end + +type t = Unaccounted | Limited of {remaining : Arith.fp} + +type cost = S.may_saturate S.t + +let encoding = + let open Data_encoding in + union + [ case + (Tag 0) + ~title:"Limited" + Arith.z_fp_encoding + (function Limited {remaining} -> Some remaining | _ -> None) + (fun remaining -> Limited {remaining}); + case + (Tag 1) + ~title:"Unaccounted" + (constant "unaccounted") + (function Unaccounted -> Some () | _ -> None) + (fun () -> Unaccounted) ] + +let pp ppf = function + | Unaccounted -> + Format.fprintf ppf "unaccounted" + | Limited {remaining} -> + Format.fprintf ppf "%a units remaining" Arith.pp remaining + +let cost_encoding = S.z_encoding + +let pp_cost fmt z = S.pp fmt z + +let allocation_weight = + S.(mul_fast scaling_factor (S.mul_safe_of_int_exn 2)) |> S.mul_safe_exn + +let step_weight = scaling_factor + +let read_base_weight = + S.(mul_fast scaling_factor (S.mul_safe_of_int_exn 100)) |> S.mul_safe_exn + +let write_base_weight = + S.(mul_fast scaling_factor (S.mul_safe_of_int_exn 160)) |> S.mul_safe_exn + +let byte_read_weight = + S.(mul_fast scaling_factor (S.mul_safe_of_int_exn 10)) |> S.mul_safe_exn + +let byte_written_weight = + S.(mul_fast scaling_factor (S.mul_safe_of_int_exn 15)) |> S.mul_safe_exn + +let cost_to_milligas (cost : cost) : Arith.fp = cost + +let raw_consume gas_counter cost = + let gas = cost_to_milligas cost in + Arith.sub_opt gas_counter gas + +let alloc_cost n = + S.scale_fast allocation_weight S.(add n (S.mul_safe_of_int_exn 1)) + +let alloc_bytes_cost n = alloc_cost (S.safe_int ((n + 7) / 8)) + +let atomic_step_cost : 'a S.t -> cost = S.may_saturate + +let step_cost n = S.scale_fast step_weight n + +let free = S.zero + +let read_bytes_cost n = + S.add read_base_weight (S.scale_fast byte_read_weight (S.safe_int n)) + +let write_bytes_cost n = + S.add write_base_weight (S.scale_fast byte_written_weight (S.safe_int n)) + +let ( +@ ) x y = S.add x y + +let ( *@ ) x y = S.mul x y + +let alloc_mbytes_cost n = + alloc_cost (S.mul_safe_of_int_exn 12) +@ alloc_bytes_cost n diff --git a/src/proto_009_PsFLoren/lib_protocol/gas_limit_repr.mli b/src/proto_009_PsFLoren/lib_protocol/gas_limit_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..629679f49bbcdd7d915567720ee5d1130347132d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/gas_limit_repr.mli @@ -0,0 +1,60 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Arith : Fixed_point_repr.Full + +type t = Unaccounted | Limited of {remaining : Arith.fp} + +val encoding : t Data_encoding.encoding + +val pp : Format.formatter -> t -> unit + +type cost = Saturation_repr.may_saturate Saturation_repr.t + +val cost_encoding : cost Data_encoding.encoding + +val pp_cost : Format.formatter -> cost -> unit + +val raw_consume : Arith.fp -> cost -> Arith.fp option + +val free : cost + +val atomic_step_cost : _ Saturation_repr.t -> cost + +val step_cost : _ Saturation_repr.t -> cost + +val alloc_cost : _ Saturation_repr.t -> cost + +val alloc_bytes_cost : int -> cost + +val alloc_mbytes_cost : int -> cost + +val read_bytes_cost : int -> cost + +val write_bytes_cost : int -> cost + +val ( *@ ) : _ Saturation_repr.t -> cost -> cost + +val ( +@ ) : cost -> cost -> cost diff --git a/src/proto_009_PsFLoren/lib_protocol/helpers_services.ml b/src/proto_009_PsFLoren/lib_protocol/helpers_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..434a838fc6bd55853a2dbb7f5c88ea5edeb535c9 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/helpers_services.ml @@ -0,0 +1,1186 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += Cannot_parse_operation (* `Branch *) + +type error += Cannot_serialize_log + +let () = + register_error_kind + `Branch + ~id:"operation.cannot_parse" + ~title:"Cannot parse operation" + ~description:"The operation is ill-formed or for another protocol version" + ~pp:(fun ppf () -> Format.fprintf ppf "The operation cannot be parsed") + Data_encoding.unit + (function Cannot_parse_operation -> Some () | _ -> None) + (fun () -> Cannot_parse_operation) ; + (* Cannot serialize log *) + register_error_kind + `Temporary + ~id:"michelson_v1.cannot_serialize_log" + ~title:"Not enough gas to serialize execution trace" + ~description: + "Execution trace with stacks was to big to be serialized with the \ + provided gas" + Data_encoding.empty + (function Cannot_serialize_log -> Some () | _ -> None) + (fun () -> Cannot_serialize_log) + +let parse_operation (op : Operation.raw) = + match + Data_encoding.Binary.of_bytes Operation.protocol_data_encoding op.proto + with + | Some protocol_data -> + ok {shell = op.shell; protocol_data} + | None -> + error Cannot_parse_operation + +let path = RPC_path.(open_root / "helpers") + +module Scripts = struct + module S = struct + open Data_encoding + + let path = RPC_path.(path / "scripts") + + let unparsing_mode_encoding = + let open Script_ir_translator in + union + ~tag_size:`Uint8 + [ case + (Tag 0) + ~title:"Readable" + (constant "Readable") + (function + | Readable -> Some () | Optimized | Optimized_legacy -> None) + (fun () -> Readable); + case + (Tag 1) + ~title:"Optimized" + (constant "Optimized") + (function + | Optimized -> Some () | Readable | Optimized_legacy -> None) + (fun () -> Optimized); + case + (Tag 2) + ~title:"Optimized_legacy" + (constant "Optimized_legacy") + (function + | Optimized_legacy -> Some () | Readable | Optimized -> None) + (fun () -> Optimized_legacy) ] + + let run_code_input_encoding = + merge_objs + (obj10 + (req "script" Script.expr_encoding) + (req "storage" Script.expr_encoding) + (req "input" Script.expr_encoding) + (req "amount" Tez.encoding) + (req "balance" Tez.encoding) + (req "chain_id" Chain_id.encoding) + (opt "source" Contract.encoding) + (opt "payer" Contract.encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (dft "entrypoint" string "default")) + (obj1 (opt "unparsing_mode" unparsing_mode_encoding)) + + let trace_encoding = + def "scripted.trace" @@ list + @@ obj3 + (req "location" Script.location_encoding) + (req "gas" Gas.encoding) + (req + "stack" + (list + (obj2 (req "item" Script.expr_encoding) (opt "annot" string)))) + + let run_code = + RPC_service.post_service + ~description:"Run a piece of code in the current context" + ~query:RPC_query.empty + ~input:run_code_input_encoding + ~output: + (conv + (fun (storage, operations, lazy_storage_diff) -> + (storage, operations, lazy_storage_diff, lazy_storage_diff)) + (fun ( storage, + operations, + legacy_lazy_storage_diff, + lazy_storage_diff ) -> + let lazy_storage_diff = + Option.either lazy_storage_diff legacy_lazy_storage_diff + in + (storage, operations, lazy_storage_diff)) + (obj4 + (req "storage" Script.expr_encoding) + (req "operations" (list Operation.internal_operation_encoding)) + (opt "big_map_diff" Lazy_storage.legacy_big_map_diff_encoding) + (opt "lazy_storage_diff" Lazy_storage.encoding))) + RPC_path.(path / "run_code") + + let trace_code = + RPC_service.post_service + ~description: + "Run a piece of code in the current context, keeping a trace" + ~query:RPC_query.empty + ~input:run_code_input_encoding + ~output: + (conv + (fun (storage, operations, trace, lazy_storage_diff) -> + ( storage, + operations, + trace, + lazy_storage_diff, + lazy_storage_diff )) + (fun ( storage, + operations, + trace, + legacy_lazy_storage_diff, + lazy_storage_diff ) -> + let lazy_storage_diff = + Option.either lazy_storage_diff legacy_lazy_storage_diff + in + (storage, operations, trace, lazy_storage_diff)) + (obj5 + (req "storage" Script.expr_encoding) + (req "operations" (list Operation.internal_operation_encoding)) + (req "trace" trace_encoding) + (opt "big_map_diff" Lazy_storage.legacy_big_map_diff_encoding) + (opt "lazy_storage_diff" Lazy_storage.encoding))) + RPC_path.(path / "trace_code") + + let typecheck_code = + RPC_service.post_service + ~description:"Typecheck a piece of code in the current context" + ~query:RPC_query.empty + ~input: + (obj3 + (req "program" Script.expr_encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (opt "legacy" bool)) + ~output: + (obj2 + (req "type_map" Script_tc_errors_registration.type_map_enc) + (req "gas" Gas.encoding)) + RPC_path.(path / "typecheck_code") + + let typecheck_data = + RPC_service.post_service + ~description: + "Check that some data expression is well formed and of a given type \ + in the current context" + ~query:RPC_query.empty + ~input: + (obj4 + (req "data" Script.expr_encoding) + (req "type" Script.expr_encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (opt "legacy" bool)) + ~output:(obj1 (req "gas" Gas.encoding)) + RPC_path.(path / "typecheck_data") + + let pack_data = + RPC_service.post_service + ~description: + "Computes the serialized version of some data expression using the \ + same algorithm as script instruction PACK" + ~input: + (obj3 + (req "data" Script.expr_encoding) + (req "type" Script.expr_encoding) + (opt "gas" Gas.Arith.z_integral_encoding)) + ~output:(obj2 (req "packed" bytes) (req "gas" Gas.encoding)) + ~query:RPC_query.empty + RPC_path.(path / "pack_data") + + let normalize_data = + RPC_service.post_service + ~description: + "Normalizes some data expression using the requested unparsing mode" + ~input: + (obj4 + (req "data" Script.expr_encoding) + (req "type" Script.expr_encoding) + (req "unparsing_mode" unparsing_mode_encoding) + (opt "legacy" bool)) + ~output:(obj1 (req "normalized" Script.expr_encoding)) + ~query:RPC_query.empty + RPC_path.(path / "normalize_data") + + let normalize_script = + RPC_service.post_service + ~description: + "Normalizes a Michelson script using the requested unparsing mode" + ~input: + (obj2 + (req "script" Script.expr_encoding) + (req "unparsing_mode" unparsing_mode_encoding)) + ~output:(obj1 (req "normalized" Script.expr_encoding)) + ~query:RPC_query.empty + RPC_path.(path / "normalize_script") + + let run_operation = + RPC_service.post_service + ~description:"Run an operation without signature checks" + ~query:RPC_query.empty + ~input: + (obj2 + (req "operation" Operation.encoding) + (req "chain_id" Chain_id.encoding)) + ~output:Apply_results.operation_data_and_metadata_encoding + RPC_path.(path / "run_operation") + + let entrypoint_type = + RPC_service.post_service + ~description:"Return the type of the given entrypoint" + ~query:RPC_query.empty + ~input: + (obj2 + (req "script" Script.expr_encoding) + (dft "entrypoint" string "default")) + ~output:(obj1 (req "entrypoint_type" Script.expr_encoding)) + RPC_path.(path / "entrypoint") + + let list_entrypoints = + RPC_service.post_service + ~description:"Return the list of entrypoints of the given script" + ~query:RPC_query.empty + ~input:(obj1 (req "script" Script.expr_encoding)) + ~output: + (obj2 + (dft + "unreachable" + (Data_encoding.list + (obj1 + (req + "path" + (Data_encoding.list + Michelson_v1_primitives.prim_encoding)))) + []) + (req "entrypoints" (assoc Script.expr_encoding))) + RPC_path.(path / "entrypoints") + end + + module type UNPARSING_MODE = sig + val unparsing_mode : Script_ir_translator.unparsing_mode + end + + module Traced_interpreter (Unparsing_mode : UNPARSING_MODE) = struct + type log_element = + | Log : + context * Script.location * 'a * 'a Script_typed_ir.stack_ty + -> log_element + + let unparse_stack ctxt (stack, stack_ty) = + (* We drop the gas limit as this function is only used for debugging/errors. *) + let ctxt = Gas.set_unlimited ctxt in + let rec unparse_stack : + type a. + a Script_typed_ir.stack_ty * a -> + (Script.expr * string option) list tzresult Lwt.t = function + | (Empty_t, ()) -> + return_nil + | (Item_t (ty, rest_ty, annot), (v, rest)) -> + Script_ir_translator.unparse_data + ctxt + Unparsing_mode.unparsing_mode + ty + v + >>=? fun (data, _ctxt) -> + unparse_stack (rest_ty, rest) + >|=? fun rest -> + let annot = + match Script_ir_annot.unparse_var_annot annot with + | [] -> + None + | [a] -> + Some a + | _ -> + assert false + in + let data = Micheline.strip_locations data in + (data, annot) :: rest + in + unparse_stack (stack_ty, stack) + + module Trace_logger () : Script_interpreter.STEP_LOGGER = struct + let log : log_element list ref = ref [] + + let log_interp ctxt (descr : (_, _) Script_typed_ir.descr) stack = + log := Log (ctxt, descr.loc, stack, descr.bef) :: !log + + let log_entry _ctxt _descr _stack = () + + let log_exit ctxt (descr : (_, _) Script_typed_ir.descr) stack = + log := Log (ctxt, descr.loc, stack, descr.aft) :: !log + + let get_log () = + map_s + (fun (Log (ctxt, loc, stack, stack_ty)) -> + trace Cannot_serialize_log (unparse_stack ctxt (stack, stack_ty)) + >>=? fun stack -> return (loc, Gas.level ctxt, stack)) + !log + >>=? fun res -> return (Some (List.rev res)) + end + + let execute ctxt step_constants ~script ~entrypoint ~parameter = + let module Logger = Trace_logger () in + let open Script_interpreter in + let logger = (module Logger : STEP_LOGGER) in + execute + ~logger + ctxt + Unparsing_mode.unparsing_mode + step_constants + ~script + ~entrypoint + ~parameter + ~internal:true + >>=? fun {ctxt; storage; lazy_storage_diff; operations} -> + Logger.get_log () + >|=? fun trace -> + let trace = Option.value ~default:[] trace in + ({ctxt; storage; lazy_storage_diff; operations}, trace) + end + + let typecheck_data : + legacy:bool -> + context -> + Script.expr * Script.expr -> + context tzresult Lwt.t = + fun ~legacy ctxt (data, exp_ty) -> + record_trace + (Script_tc_errors.Ill_formed_type (None, exp_ty, 0)) + (Script_ir_translator.parse_parameter_ty + ctxt + ~legacy + (Micheline.root exp_ty)) + >>?= fun (Ex_ty exp_ty, ctxt) -> + trace_eval + (fun () -> + Lwt.return + ( Script_ir_translator.serialize_ty_for_error ctxt exp_ty + >|? fun (exp_ty, _ctxt) -> + Script_tc_errors.Ill_typed_data (None, data, exp_ty) )) + (let allow_forged = + true + (* Safe since we ignore the value afterwards. *) + in + Script_ir_translator.parse_data + ctxt + ~legacy + ~allow_forged + exp_ty + (Micheline.root data)) + >|=? fun (_, ctxt) -> ctxt + + let register () = + let open Services_registration in + let originate_dummy_contract ctxt script balance = + let ctxt = Contract.init_origination_nonce ctxt Operation_hash.zero in + Lwt.return (Contract.fresh_contract_from_current_nonce ctxt) + >>=? fun (ctxt, dummy_contract) -> + Contract.originate + ctxt + dummy_contract + ~balance + ~delegate:None + ~script:(script, None) + >>=? fun ctxt -> return (ctxt, dummy_contract) + in + register0 + S.run_code + (fun ctxt + () + ( ( code, + storage, + parameter, + amount, + balance, + chain_id, + source, + payer, + gas, + entrypoint ), + unparsing_mode ) + -> + let unparsing_mode = Option.value ~default:Readable unparsing_mode in + let storage = Script.lazy_expr storage in + let code = Script.lazy_expr code in + originate_dummy_contract ctxt {storage; code} balance + >>=? fun (ctxt, dummy_contract) -> + let (source, payer) = + match (source, payer) with + | (Some source, Some payer) -> + (source, payer) + | (Some source, None) -> + (source, source) + | (None, Some payer) -> + (payer, payer) + | (None, None) -> + (dummy_contract, dummy_contract) + in + let gas = + match gas with + | Some gas -> + gas + | None -> + Constants.hard_gas_limit_per_operation ctxt + in + let ctxt = Gas.set_limit ctxt gas in + let step_constants = + let open Script_interpreter in + {source; payer; self = dummy_contract; amount; chain_id} + in + Script_interpreter.execute + ctxt + unparsing_mode + step_constants + ~script:{storage; code} + ~entrypoint + ~parameter + ~internal:true + >|=? fun {Script_interpreter.storage; operations; lazy_storage_diff; _} -> + (storage, operations, lazy_storage_diff)) ; + register0 + S.trace_code + (fun ctxt + () + ( ( code, + storage, + parameter, + amount, + balance, + chain_id, + source, + payer, + gas, + entrypoint ), + unparsing_mode ) + -> + let unparsing_mode = Option.value ~default:Readable unparsing_mode in + let storage = Script.lazy_expr storage in + let code = Script.lazy_expr code in + originate_dummy_contract ctxt {storage; code} balance + >>=? fun (ctxt, dummy_contract) -> + let (source, payer) = + match (source, payer) with + | (Some source, Some payer) -> + (source, payer) + | (Some source, None) -> + (source, source) + | (None, Some payer) -> + (payer, payer) + | (None, None) -> + (dummy_contract, dummy_contract) + in + let gas = + match gas with + | Some gas -> + gas + | None -> + Constants.hard_gas_limit_per_operation ctxt + in + let ctxt = Gas.set_limit ctxt gas in + let step_constants = + let open Script_interpreter in + {source; payer; self = dummy_contract; amount; chain_id} + in + let module Unparsing_mode = struct + let unparsing_mode = unparsing_mode + end in + let module Interp = Traced_interpreter (Unparsing_mode) in + Interp.execute + ctxt + step_constants + ~script:{storage; code} + ~entrypoint + ~parameter + >|=? fun ( { Script_interpreter.storage; + operations; + lazy_storage_diff; + _ }, + trace ) -> + (storage, operations, trace, lazy_storage_diff)) ; + register0 S.typecheck_code (fun ctxt () (expr, maybe_gas, legacy) -> + let legacy = Option.value ~default:false legacy in + let ctxt = + match maybe_gas with + | None -> + Gas.set_unlimited ctxt + | Some gas -> + Gas.set_limit ctxt gas + in + Script_ir_translator.typecheck_code ~legacy ctxt expr + >|=? fun (res, ctxt) -> (res, Gas.level ctxt)) ; + register0 S.typecheck_data (fun ctxt () (data, ty, maybe_gas, legacy) -> + let legacy = Option.value ~default:false legacy in + let ctxt = + match maybe_gas with + | None -> + Gas.set_unlimited ctxt + | Some gas -> + Gas.set_limit ctxt gas + in + typecheck_data ~legacy ctxt (data, ty) >|=? fun ctxt -> Gas.level ctxt) ; + register0 S.pack_data (fun ctxt () (expr, typ, maybe_gas) -> + let open Script_ir_translator in + let ctxt = + match maybe_gas with + | None -> + Gas.set_unlimited ctxt + | Some gas -> + Gas.set_limit ctxt gas + in + parse_packable_ty ctxt ~legacy:true (Micheline.root typ) + >>?= fun (Ex_ty typ, ctxt) -> + parse_data + ctxt + ~legacy:true + ~allow_forged:true + typ + (Micheline.root expr) + >>=? fun (data, ctxt) -> + Script_ir_translator.pack_data ctxt typ data + >|=? fun (bytes, ctxt) -> (bytes, Gas.level ctxt)) ; + register0 + S.normalize_data + (fun ctxt () (expr, typ, unparsing_mode, legacy) -> + let open Script_ir_translator in + let legacy = Option.value ~default:false legacy in + let ctxt = Gas.set_unlimited ctxt in + Script_ir_translator.parse_any_ty ctxt ~legacy (Micheline.root typ) + >>?= fun (Ex_ty typ, ctxt) -> + parse_data ctxt ~legacy ~allow_forged:true typ (Micheline.root expr) + >>=? fun (data, ctxt) -> + Script_ir_translator.unparse_data ctxt unparsing_mode typ data + >|=? fun (normalized, _ctxt) -> Micheline.strip_locations normalized) ; + register0 S.normalize_script (fun ctxt () (script, unparsing_mode) -> + let ctxt = Gas.set_unlimited ctxt in + Script_ir_translator.unparse_code + ctxt + unparsing_mode + (Micheline.root script) + >|=? fun (normalized, _ctxt) -> Micheline.strip_locations normalized) ; + register0 + S.run_operation + (fun ctxt + () + ({shell; protocol_data = Operation_data protocol_data}, chain_id) + -> + (* this code is a duplicate of Apply without signature check *) + let partial_precheck_manager_contents (type kind) ctxt + (op : kind Kind.manager contents) : context tzresult Lwt.t = + let (Manager_operation + {source; fee; counter; operation; gas_limit; storage_limit}) = + op + in + Gas.check_limit ctxt gas_limit + >>?= fun () -> + let ctxt = Gas.set_limit ctxt gas_limit in + Fees.check_storage_limit ctxt storage_limit + >>?= fun () -> + Contract.must_be_allocated ctxt (Contract.implicit_contract source) + >>=? fun () -> + Contract.check_counter_increment ctxt source counter + >>=? fun () -> + ( match operation with + | Reveal pk -> + Contract.reveal_manager_key ctxt source pk + | Transaction {parameters; _} -> + (* Here the data comes already deserialized, so we need to fake the deserialization to mimic apply *) + let arg_bytes = + Data_encoding.Binary.to_bytes_exn + Script.lazy_expr_encoding + parameters + in + let arg = + match + Data_encoding.Binary.of_bytes + Script.lazy_expr_encoding + arg_bytes + with + | Some arg -> + arg + | None -> + assert false + in + (* Fail quickly if not enough gas for minimal deserialization cost *) + Lwt.return + @@ record_trace Apply.Gas_quota_exceeded_init_deserialize + @@ ( Gas.check_enough ctxt (Script.minimal_deserialize_cost arg) + >>? fun () -> + (* Fail if not enough gas for complete deserialization cost *) + Script.force_decode_in_context ctxt arg + >|? fun (_arg, ctxt) -> ctxt ) + | Origination {script; _} -> + (* Here the data comes already deserialized, so we need to fake the deserialization to mimic apply *) + let script_bytes = + Data_encoding.Binary.to_bytes_exn Script.encoding script + in + let script = + match + Data_encoding.Binary.of_bytes Script.encoding script_bytes + with + | Some script -> + script + | None -> + assert false + in + Lwt.return + @@ record_trace Apply.Gas_quota_exceeded_init_deserialize + @@ ( Gas.( + check_enough + (* Fail quickly if not enough gas for minimal deserialization cost *) + ctxt + ( Script.minimal_deserialize_cost script.code + +@ Script.minimal_deserialize_cost script.storage )) + >>? fun () -> + (* Fail if not enough gas for complete deserialization cost *) + Script.force_decode_in_context ctxt script.code + >>? fun (_code, ctxt) -> + Script.force_decode_in_context ctxt script.storage + >|? fun (_storage, ctxt) -> ctxt ) + | _ -> + return ctxt ) + >>=? fun ctxt -> + Contract.get_manager_key ctxt source + >>=? fun _public_key -> + (* signature check unplugged from here *) + Contract.increment_counter ctxt source + >>=? fun ctxt -> + Contract.spend ctxt (Contract.implicit_contract source) fee + in + let rec partial_precheck_manager_contents_list : + type kind. + Alpha_context.t -> + kind Kind.manager contents_list -> + context tzresult Lwt.t = + fun ctxt contents_list -> + match contents_list with + | Single (Manager_operation _ as op) -> + partial_precheck_manager_contents ctxt op + | Cons ((Manager_operation _ as op), rest) -> + partial_precheck_manager_contents ctxt op + >>=? fun ctxt -> partial_precheck_manager_contents_list ctxt rest + in + let ret contents = + ( Operation_data protocol_data, + Apply_results.Operation_metadata {contents} ) + in + let operation : _ operation = {shell; protocol_data} in + let hash = Operation.hash {shell; protocol_data} in + let ctxt = Contract.init_origination_nonce ctxt hash in + let baker = Signature.Public_key_hash.zero in + match protocol_data.contents with + | Single (Manager_operation _) as op -> + partial_precheck_manager_contents_list ctxt op + >>=? fun ctxt -> + Apply.apply_manager_contents_list ctxt Optimized baker chain_id op + >|= fun (_ctxt, result) -> ok @@ ret result + | Cons (Manager_operation _, _) as op -> + partial_precheck_manager_contents_list ctxt op + >>=? fun ctxt -> + Apply.apply_manager_contents_list ctxt Optimized baker chain_id op + >|= fun (_ctxt, result) -> ok @@ ret result + | _ -> + Apply.apply_contents_list + ctxt + chain_id + Optimized + shell.branch + baker + operation + operation.protocol_data.contents + >|=? fun (_ctxt, result) -> ret result) ; + register0 S.entrypoint_type (fun ctxt () (expr, entrypoint) -> + let ctxt = Gas.set_unlimited ctxt in + let legacy = false in + let open Script_ir_translator in + Lwt.return + ( parse_toplevel ~legacy expr + >>? (fun (arg_type, _, _, root_name) -> + parse_parameter_ty ctxt ~legacy arg_type + >>? fun (Ex_ty arg_type, _) -> + Script_ir_translator.find_entrypoint + ~root_name + arg_type + entrypoint) + >>? fun (_f, Ex_ty ty) -> + unparse_ty ctxt ty + >|? fun (ty_node, _) -> Micheline.strip_locations ty_node )) ; + register0 S.list_entrypoints (fun ctxt () expr -> + let ctxt = Gas.set_unlimited ctxt in + let legacy = false in + let open Script_ir_translator in + Lwt.return + ( parse_toplevel ~legacy expr + >>? fun (arg_type, _, _, root_name) -> + parse_parameter_ty ctxt ~legacy arg_type + >>? fun (Ex_ty arg_type, _) -> + Script_ir_translator.list_entrypoints ~root_name arg_type ctxt + >|? fun (unreachable_entrypoint, map) -> + ( unreachable_entrypoint, + Entrypoints_map.fold + (fun entry (_, ty) acc -> + (entry, Micheline.strip_locations ty) :: acc) + map + [] ) )) + + let run_code ctxt block ?unparsing_mode ?gas ?(entrypoint = "default") + ~script ~storage ~input ~amount ~balance ~chain_id ~source ~payer = + RPC_context.make_call0 + S.run_code + ctxt + block + () + ( ( script, + storage, + input, + amount, + balance, + chain_id, + source, + payer, + gas, + entrypoint ), + unparsing_mode ) + + let trace_code ctxt block ?unparsing_mode ?gas ?(entrypoint = "default") + ~script ~storage ~input ~amount ~balance ~chain_id ~source ~payer = + RPC_context.make_call0 + S.trace_code + ctxt + block + () + ( ( script, + storage, + input, + amount, + balance, + chain_id, + source, + payer, + gas, + entrypoint ), + unparsing_mode ) + + let typecheck_code ctxt block ?gas ?legacy ~script = + RPC_context.make_call0 S.typecheck_code ctxt block () (script, gas, legacy) + + let typecheck_data ctxt block ?gas ?legacy ~data ~ty = + RPC_context.make_call0 + S.typecheck_data + ctxt + block + () + (data, ty, gas, legacy) + + let pack_data ctxt block ?gas ~data ~ty = + RPC_context.make_call0 S.pack_data ctxt block () (data, ty, gas) + + let normalize_data ctxt block ?legacy ~data ~ty ~unparsing_mode = + RPC_context.make_call0 + S.normalize_data + ctxt + block + () + (data, ty, unparsing_mode, legacy) + + let normalize_script ctxt block ~script ~unparsing_mode = + RPC_context.make_call0 + S.normalize_script + ctxt + block + () + (script, unparsing_mode) + + let run_operation ctxt block ~op ~chain_id = + RPC_context.make_call0 S.run_operation ctxt block () (op, chain_id) + + let entrypoint_type ctxt block ~script ~entrypoint = + RPC_context.make_call0 S.entrypoint_type ctxt block () (script, entrypoint) + + let list_entrypoints ctxt block ~script = + RPC_context.make_call0 S.list_entrypoints ctxt block () script +end + +module Forge = struct + module S = struct + open Data_encoding + + let path = RPC_path.(path / "forge") + + let operations = + RPC_service.post_service + ~description:"Forge an operation" + ~query:RPC_query.empty + ~input:Operation.unsigned_encoding + ~output:bytes + RPC_path.(path / "operations") + + let empty_proof_of_work_nonce = + Bytes.make Constants_repr.proof_of_work_nonce_size '\000' + + let protocol_data = + RPC_service.post_service + ~description:"Forge the protocol-specific part of a block header" + ~query:RPC_query.empty + ~input: + (obj3 + (req "priority" uint16) + (opt "nonce_hash" Nonce_hash.encoding) + (dft + "proof_of_work_nonce" + (Fixed.bytes Alpha_context.Constants.proof_of_work_nonce_size) + empty_proof_of_work_nonce)) + ~output:(obj1 (req "protocol_data" bytes)) + RPC_path.(path / "protocol_data") + end + + let register () = + let open Services_registration in + register0_noctxt S.operations (fun () (shell, proto) -> + return + (Data_encoding.Binary.to_bytes_exn + Operation.unsigned_encoding + (shell, proto))) ; + register0_noctxt + S.protocol_data + (fun () (priority, seed_nonce_hash, proof_of_work_nonce) -> + return + (Data_encoding.Binary.to_bytes_exn + Block_header.contents_encoding + {priority; seed_nonce_hash; proof_of_work_nonce})) + + module Manager = struct + let operations ctxt block ~branch ~source ?sourcePubKey ~counter ~fee + ~gas_limit ~storage_limit operations = + Contract_services.manager_key ctxt block source + >>= function + | Error _ as e -> + Lwt.return e + | Ok revealed -> + let ops = + List.map + (fun (Manager operation) -> + Contents + (Manager_operation + { + source; + counter; + operation; + fee; + gas_limit; + storage_limit; + })) + operations + in + let ops = + match (sourcePubKey, revealed) with + | (None, _) | (_, Some _) -> + ops + | (Some pk, None) -> + let operation = Reveal pk in + Contents + (Manager_operation + { + source; + counter; + operation; + fee; + gas_limit; + storage_limit; + }) + :: ops + in + RPC_context.make_call0 + S.operations + ctxt + block + () + ({branch}, Operation.of_list ops) + + let reveal ctxt block ~branch ~source ~sourcePubKey ~counter ~fee () = + operations + ctxt + block + ~branch + ~source + ~sourcePubKey + ~counter + ~fee + ~gas_limit:Gas.Arith.zero + ~storage_limit:Z.zero + [] + + let transaction ctxt block ~branch ~source ?sourcePubKey ~counter ~amount + ~destination ?(entrypoint = "default") ?parameters ~gas_limit + ~storage_limit ~fee () = + let parameters = + Option.fold + ~some:Script.lazy_expr + ~none:Script.unit_parameter + parameters + in + operations + ctxt + block + ~branch + ~source + ?sourcePubKey + ~counter + ~fee + ~gas_limit + ~storage_limit + [Manager (Transaction {amount; parameters; destination; entrypoint})] + + let origination ctxt block ~branch ~source ?sourcePubKey ~counter ~balance + ?delegatePubKey ~script ~gas_limit ~storage_limit ~fee () = + operations + ctxt + block + ~branch + ~source + ?sourcePubKey + ~counter + ~fee + ~gas_limit + ~storage_limit + [ Manager + (Origination + { + delegate = delegatePubKey; + script; + credit = balance; + preorigination = None; + }) ] + + let delegation ctxt block ~branch ~source ?sourcePubKey ~counter ~fee + delegate = + operations + ctxt + block + ~branch + ~source + ?sourcePubKey + ~counter + ~fee + ~gas_limit:Gas.Arith.zero + ~storage_limit:Z.zero + [Manager (Delegation delegate)] + end + + let operation ctxt block ~branch operation = + RPC_context.make_call0 + S.operations + ctxt + block + () + ({branch}, Contents_list (Single operation)) + + let endorsement ctxt b ~branch ~level () = + operation ctxt b ~branch (Endorsement {level}) + + let proposals ctxt b ~branch ~source ~period ~proposals () = + operation ctxt b ~branch (Proposals {source; period; proposals}) + + let ballot ctxt b ~branch ~source ~period ~proposal ~ballot () = + operation ctxt b ~branch (Ballot {source; period; proposal; ballot}) + + let failing_noop ctxt b ~branch ~message () = + operation ctxt b ~branch (Failing_noop message) + + let seed_nonce_revelation ctxt block ~branch ~level ~nonce () = + operation ctxt block ~branch (Seed_nonce_revelation {level; nonce}) + + let double_baking_evidence ctxt block ~branch ~bh1 ~bh2 () = + operation ctxt block ~branch (Double_baking_evidence {bh1; bh2}) + + let double_endorsement_evidence ctxt block ~branch ~op1 ~op2 ~slot () = + operation ctxt block ~branch (Double_endorsement_evidence {op1; op2; slot}) + + let empty_proof_of_work_nonce = + Bytes.make Constants_repr.proof_of_work_nonce_size '\000' + + let protocol_data ctxt block ~priority ?seed_nonce_hash + ?(proof_of_work_nonce = empty_proof_of_work_nonce) () = + RPC_context.make_call0 + S.protocol_data + ctxt + block + () + (priority, seed_nonce_hash, proof_of_work_nonce) +end + +module Parse = struct + module S = struct + open Data_encoding + + let path = RPC_path.(path / "parse") + + let operations = + RPC_service.post_service + ~description:"Parse operations" + ~query:RPC_query.empty + ~input: + (obj2 + (req "operations" (list (dynamic_size Operation.raw_encoding))) + (opt "check_signature" bool)) + ~output:(list (dynamic_size Operation.encoding)) + RPC_path.(path / "operations") + + let block = + RPC_service.post_service + ~description:"Parse a block" + ~query:RPC_query.empty + ~input:Block_header.raw_encoding + ~output:Block_header.protocol_data_encoding + RPC_path.(path / "block") + end + + let parse_protocol_data protocol_data = + match + Data_encoding.Binary.of_bytes + Block_header.protocol_data_encoding + protocol_data + with + | None -> + failwith "Cant_parse_protocol_data" + | Some protocol_data -> + protocol_data + + let register () = + let open Services_registration in + register0 S.operations (fun _ctxt () (operations, check) -> + map_s + (fun raw -> + parse_operation raw + >>?= fun op -> + ( match check with + | Some true -> + return_unit (* FIXME *) + (* I.check_signature ctxt *) + (* op.protocol_data.signature op.shell op.protocol_data.contents *) + | Some false | None -> + return_unit ) + >|=? fun () -> op) + operations) ; + register0_noctxt S.block (fun () raw_block -> + return @@ parse_protocol_data raw_block.protocol_data) + + let operations ctxt block ?check operations = + RPC_context.make_call0 S.operations ctxt block () (operations, check) + + let block ctxt block shell protocol_data = + RPC_context.make_call0 + S.block + ctxt + block + () + ({shell; protocol_data} : Block_header.raw) +end + +module S = struct + open Data_encoding + + type level_query = {offset : int32} + + let level_query : level_query RPC_query.t = + let open RPC_query in + query (fun offset -> {offset}) + |+ field "offset" RPC_arg.int32 0l (fun t -> t.offset) + |> seal + + let current_level = + RPC_service.get_service + ~description: + "Returns the level of the interrogated block, or the one of a block \ + located `offset` blocks after in the chain (or before when \ + negative). For instance, the next block if `offset` is 1." + ~query:level_query + ~output:Level.compat_encoding + RPC_path.(path / "current_level") + + let levels_in_current_cycle = + RPC_service.get_service + ~description:"Levels of a cycle" + ~query:level_query + ~output: + (obj2 (req "first" Raw_level.encoding) (req "last" Raw_level.encoding)) + RPC_path.(path / "levels_in_current_cycle") +end + +let register () = + Scripts.register () ; + Forge.register () ; + Parse.register () ; + let open Services_registration in + register0 S.current_level (fun ctxt q () -> + let level = + Level.from_raw ctxt ~offset:q.offset (Level.current ctxt).level + in + Alpha_context.Voting_period.get_rpc_fixed_current_info ctxt + >|=? fun {voting_period; remaining; _} -> + let blocks_per_voting_period = Constants.blocks_per_voting_period ctxt in + let div_rem = Int32.(rem q.offset blocks_per_voting_period) in + let index_offset = + Int32.( + add + (div q.offset blocks_per_voting_period) + (if Compare.Int32.(div_rem > remaining) then 1l else 0l)) + in + let voting_period_index = Int32.add voting_period.index index_offset in + let start_position = + Int32.( + add + voting_period.start_position + (mul index_offset blocks_per_voting_period)) + in + let voting_period_position = + Int32.(sub level.level_position start_position) + in + Level.to_deprecated_type + level + ~voting_period_index + ~voting_period_position) ; + register0 S.levels_in_current_cycle (fun ctxt q () -> + let levels = Level.levels_in_current_cycle ctxt ~offset:q.offset () in + match levels with + | [] -> + raise Not_found + | _ -> + let first = List.hd (List.rev levels) in + let last = List.hd levels in + return (first.level, last.level)) + +let current_level ctxt ?(offset = 0l) block = + RPC_context.make_call0 S.current_level ctxt block {offset} () + +let levels_in_current_cycle ctxt ?(offset = 0l) block = + RPC_context.make_call0 S.levels_in_current_cycle ctxt block {offset} () diff --git a/src/proto_009_PsFLoren/lib_protocol/helpers_services.mli b/src/proto_009_PsFLoren/lib_protocol/helpers_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..399a441929bc3a470721c03253091873d347f4e3 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/helpers_services.mli @@ -0,0 +1,312 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += Cannot_parse_operation (* `Branch *) + +type error += Cannot_serialize_log + +val current_level : + 'a #RPC_context.simple -> + ?offset:int32 -> + 'a -> + Level.compat_t shell_tzresult Lwt.t + +val levels_in_current_cycle : + 'a #RPC_context.simple -> + ?offset:int32 -> + 'a -> + (Raw_level.t * Raw_level.t) shell_tzresult Lwt.t + +module Scripts : sig + val run_code : + 'a #RPC_context.simple -> + 'a -> + ?unparsing_mode:Script_ir_translator.unparsing_mode -> + ?gas:Gas.Arith.integral -> + ?entrypoint:string -> + script:Script.expr -> + storage:Script.expr -> + input:Script.expr -> + amount:Tez.t -> + balance:Tez.t -> + chain_id:Chain_id.t -> + source:Contract.t option -> + payer:Contract.t option -> + (Script.expr * packed_internal_operation list * Lazy_storage.diffs option) + shell_tzresult + Lwt.t + + val trace_code : + 'a #RPC_context.simple -> + 'a -> + ?unparsing_mode:Script_ir_translator.unparsing_mode -> + ?gas:Gas.Arith.integral -> + ?entrypoint:string -> + script:Script.expr -> + storage:Script.expr -> + input:Script.expr -> + amount:Tez.t -> + balance:Tez.t -> + chain_id:Chain_id.t -> + source:Contract.t option -> + payer:Contract.t option -> + ( Script.expr + * packed_internal_operation list + * Script_interpreter.execution_trace + * Lazy_storage.diffs option ) + shell_tzresult + Lwt.t + + val typecheck_code : + 'a #RPC_context.simple -> + 'a -> + ?gas:Gas.Arith.integral -> + ?legacy:bool -> + script:Script.expr -> + (Script_tc_errors.type_map * Gas.t) shell_tzresult Lwt.t + + val typecheck_data : + 'a #RPC_context.simple -> + 'a -> + ?gas:Gas.Arith.integral -> + ?legacy:bool -> + data:Script.expr -> + ty:Script.expr -> + Gas.t shell_tzresult Lwt.t + + val pack_data : + 'a #RPC_context.simple -> + 'a -> + ?gas:Gas.Arith.integral -> + data:Script.expr -> + ty:Script.expr -> + (bytes * Gas.t) shell_tzresult Lwt.t + + val normalize_data : + 'a #RPC_context.simple -> + 'a -> + ?legacy:bool -> + data:Script.expr -> + ty:Script.expr -> + unparsing_mode:Script_ir_translator.unparsing_mode -> + Script.expr shell_tzresult Lwt.t + + val normalize_script : + 'a #RPC_context.simple -> + 'a -> + script:Script.expr -> + unparsing_mode:Script_ir_translator.unparsing_mode -> + Script.expr shell_tzresult Lwt.t + + val run_operation : + 'a #RPC_context.simple -> + 'a -> + op:packed_operation -> + chain_id:Chain_id.t -> + (packed_protocol_data * Apply_results.packed_operation_metadata) + shell_tzresult + Lwt.t + + val entrypoint_type : + 'a #RPC_context.simple -> + 'a -> + script:Script.expr -> + entrypoint:string -> + Script.expr shell_tzresult Lwt.t + + val list_entrypoints : + 'a #RPC_context.simple -> + 'a -> + script:Script.expr -> + (Michelson_v1_primitives.prim list list * (string * Script.expr) list) + shell_tzresult + Lwt.t +end + +module Forge : sig + module Manager : sig + val operations : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + source:public_key_hash -> + ?sourcePubKey:public_key -> + counter:counter -> + fee:Tez.t -> + gas_limit:Gas.Arith.integral -> + storage_limit:Z.t -> + packed_manager_operation list -> + bytes shell_tzresult Lwt.t + + val reveal : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + source:public_key_hash -> + sourcePubKey:public_key -> + counter:counter -> + fee:Tez.t -> + unit -> + bytes shell_tzresult Lwt.t + + val transaction : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + source:public_key_hash -> + ?sourcePubKey:public_key -> + counter:counter -> + amount:Tez.t -> + destination:Contract.t -> + ?entrypoint:string -> + ?parameters:Script.expr -> + gas_limit:Gas.Arith.integral -> + storage_limit:Z.t -> + fee:Tez.t -> + unit -> + bytes shell_tzresult Lwt.t + + val origination : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + source:public_key_hash -> + ?sourcePubKey:public_key -> + counter:counter -> + balance:Tez.t -> + ?delegatePubKey:public_key_hash -> + script:Script.t -> + gas_limit:Gas.Arith.integral -> + storage_limit:Z.t -> + fee:Tez.t -> + unit -> + bytes shell_tzresult Lwt.t + + val delegation : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + source:public_key_hash -> + ?sourcePubKey:public_key -> + counter:counter -> + fee:Tez.t -> + public_key_hash option -> + bytes shell_tzresult Lwt.t + end + + val endorsement : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + level:Raw_level.t -> + unit -> + bytes shell_tzresult Lwt.t + + val proposals : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + source:public_key_hash -> + period:int32 -> + proposals:Protocol_hash.t list -> + unit -> + bytes shell_tzresult Lwt.t + + val ballot : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + source:public_key_hash -> + period:int32 -> + proposal:Protocol_hash.t -> + ballot:Vote.ballot -> + unit -> + bytes shell_tzresult Lwt.t + + val failing_noop : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + message:string -> + unit -> + Bytes.t shell_tzresult Lwt.t + + val seed_nonce_revelation : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + level:Raw_level.t -> + nonce:Nonce.t -> + unit -> + bytes shell_tzresult Lwt.t + + val double_baking_evidence : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + bh1:Block_header.t -> + bh2:Block_header.t -> + unit -> + bytes shell_tzresult Lwt.t + + val double_endorsement_evidence : + 'a #RPC_context.simple -> + 'a -> + branch:Block_hash.t -> + op1:Kind.endorsement operation -> + op2:Kind.endorsement operation -> + slot:int -> + unit -> + bytes shell_tzresult Lwt.t + + val protocol_data : + 'a #RPC_context.simple -> + 'a -> + priority:int -> + ?seed_nonce_hash:Nonce_hash.t -> + ?proof_of_work_nonce:bytes -> + unit -> + bytes shell_tzresult Lwt.t +end + +module Parse : sig + val operations : + 'a #RPC_context.simple -> + 'a -> + ?check:bool -> + Operation.raw list -> + Operation.packed list shell_tzresult Lwt.t + + val block : + 'a #RPC_context.simple -> + 'a -> + Block_header.shell_header -> + bytes -> + Block_header.protocol_data shell_tzresult Lwt.t +end + +val register : unit -> unit diff --git a/src/proto_009_PsFLoren/lib_protocol/init_storage.ml b/src/proto_009_PsFLoren/lib_protocol/init_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..6ed181c481e9f9950c3679d7ae4753779266872a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/init_storage.ml @@ -0,0 +1,103 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Invoice a contract at a given address with a given amount. Returns the + updated context and a balance update receipt (singleton list). The address + must be a valid base58 hash, otherwise this is no-op and returns an empty + receipts list. + + Do not fail if something goes wrong. +*) +let invoice_contract ctxt ~address ~amount_mutez = + match Tez_repr.of_mutez amount_mutez with + | None -> + Lwt.return (ctxt, []) + | Some amount -> ( + Contract_repr.of_b58check address + >>?= (fun recipient -> + Contract_storage.credit ctxt recipient amount + >|=? fun ctxt -> + ( ctxt, + Receipt_repr. + [(Contract recipient, Credited amount, Protocol_migration)] )) + >|= function Ok res -> res | Error _ -> (ctxt, []) ) + +(* This is the genesis protocol: initialise the state *) +let prepare_first_block ctxt ~typecheck ~level ~timestamp ~fitness = + Raw_context.prepare_first_block ~level ~timestamp ~fitness ctxt + >>=? fun (previous_protocol, ctxt) -> + match previous_protocol with + | Genesis param -> + Commitment_storage.init ctxt param.commitments + >>=? fun ctxt -> + Roll_storage.init ctxt + >>=? fun ctxt -> + Seed_storage.init ctxt + >>=? fun ctxt -> + Contract_storage.init ctxt + >>=? fun ctxt -> + Bootstrap_storage.init + ctxt + ~typecheck + ?ramp_up_cycles:param.security_deposit_ramp_up_cycles + ?no_reward_cycles:param.no_reward_cycles + param.bootstrap_accounts + param.bootstrap_contracts + >>=? fun ctxt -> + Roll_storage.init_first_cycles ctxt + >>=? fun ctxt -> + Vote_storage.init + ctxt + ~start_position:(Level_storage.current ctxt).level_position + >>=? fun ctxt -> + Storage.Block_priority.init ctxt 0 + >>=? fun ctxt -> Vote_storage.update_listings ctxt + | Edo_008 -> + (* Add balance updates receipts to be attached on the first block of this + protocol - see [[prepare]] function below. Any balance updates attached + in the migration should use the [[Receipt_repr.Migration]] constructor. + *) + invoice_contract + ctxt + ~address:"tz1abmz7jiCV2GH2u81LRrGgAFFgvQgiDiaf" + ~amount_mutez:100_000_000L + >>= fun (ctxt, balance_updates) -> + Storage.Pending_migration_balance_updates.init ctxt balance_updates + +let prepare ctxt ~level ~predecessor_timestamp ~timestamp ~fitness = + Raw_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt + >>=? fun ctxt -> + Storage.Pending_migration_balance_updates.find ctxt + >>=? function + | Some balance_updates -> + Storage.Pending_migration_balance_updates.remove ctxt + >>= fun ctxt -> + (* When applying balance updates in a migration, we must attach receipts. + The balance updates returned from here will be applied in the first + block of the new protocol. *) + return (ctxt, balance_updates) + | None -> + return (ctxt, []) diff --git a/src/proto_009_PsFLoren/lib_protocol/init_storage.mli b/src/proto_009_PsFLoren/lib_protocol/init_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..899175a894d83057f7a24fe44f320f187ba7c686 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/init_storage.mli @@ -0,0 +1,46 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* This is the genesis protocol: initialise the state *) +val prepare_first_block : + Context.t -> + typecheck:(Raw_context.t -> + Script_repr.t -> + ((Script_repr.t * Lazy_storage_diff.diffs option) * Raw_context.t) + Error_monad.tzresult + Lwt.t) -> + level:int32 -> + timestamp:Time.t -> + fitness:Fitness.t -> + (Raw_context.t, Error_monad.error Error_monad.trace) Pervasives.result Lwt.t + +val prepare : + Context.t -> + level:Int32.t -> + predecessor_timestamp:Time.t -> + timestamp:Time.t -> + fitness:Fitness.t -> + (Raw_context.t * Receipt_repr.balance_updates) Error_monad.tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/lazy_storage_diff.ml b/src/proto_009_PsFLoren/lib_protocol/lazy_storage_diff.ml new file mode 100644 index 0000000000000000000000000000000000000000..92afd1bac2f646fdf3f5e247b36e2f4f46e01c6a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/lazy_storage_diff.ml @@ -0,0 +1,393 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type Next = sig + type id + + val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + + val incr : Raw_context.t -> (Raw_context.t * id) tzresult Lwt.t +end + +module type Total_bytes = sig + type id + + val init : Raw_context.t -> id -> Z.t -> Raw_context.t tzresult Lwt.t + + val get : Raw_context.t -> id -> Z.t tzresult Lwt.t + + val update : Raw_context.t -> id -> Z.t -> Raw_context.t tzresult Lwt.t +end + +(** Operations to be defined on a lazy storage type. *) +module type OPS = sig + module Id : Lazy_storage_kind.ID + + type alloc + + type updates + + val title : string + + val alloc_encoding : alloc Data_encoding.t + + val updates_encoding : updates Data_encoding.t + + val bytes_size_for_empty : Z.t + + val alloc : Raw_context.t -> id:Id.t -> alloc -> Raw_context.t tzresult Lwt.t + + val apply_updates : + Raw_context.t -> id:Id.t -> updates -> (Raw_context.t * Z.t) tzresult Lwt.t + + module Next : Next with type id := Id.t + + module Total_bytes : Total_bytes with type id := Id.t + + (** Deep copy. *) + val copy : + Raw_context.t -> from:Id.t -> to_:Id.t -> Raw_context.t tzresult Lwt.t + + (** Deep deletion. *) + val remove : Raw_context.t -> Id.t -> Raw_context.t Lwt.t +end + +module Big_map = struct + include Lazy_storage_kind.Big_map + + let bytes_size_for_big_map_key = 65 + + let bytes_size_for_empty = + let bytes_size_for_big_map = 33 in + Z.of_int bytes_size_for_big_map + + let alloc ctxt ~id {key_type; value_type} = + (* Annotations are erased to allow sharing on [Copy]. The types from the + contract code are used, these ones are only used to make sure they are + compatible during transmissions between contracts, and only need to be + compatible, annotations notwithstanding. *) + let key_type = + Micheline.strip_locations + (Script_repr.strip_annotations (Micheline.root key_type)) + in + let value_type = + Micheline.strip_locations + (Script_repr.strip_annotations (Micheline.root value_type)) + in + Storage.Big_map.Key_type.init ctxt id key_type + >>=? fun ctxt -> Storage.Big_map.Value_type.init ctxt id value_type + + let apply_update ctxt ~id + { key = _key_is_shown_only_on_the_receipt_in_print_big_map_diff; + key_hash; + value } = + match value with + | None -> + Storage.Big_map.Contents.remove (ctxt, id) key_hash + >|=? fun (ctxt, freed, existed) -> + let freed = + if existed then freed + bytes_size_for_big_map_key else freed + in + (ctxt, Z.of_int ~-freed) + | Some v -> + Storage.Big_map.Contents.add (ctxt, id) key_hash v + >|=? fun (ctxt, size_diff, existed) -> + let size_diff = + if existed then size_diff else size_diff + bytes_size_for_big_map_key + in + (ctxt, Z.of_int size_diff) + + let apply_updates ctxt ~id updates = + fold_left_s + (fun (ctxt, size) update -> + apply_update ctxt ~id update + >|=? fun (ctxt, added_size) -> (ctxt, Z.add size added_size)) + (ctxt, Z.zero) + updates + + include Storage.Big_map +end + +type ('id, 'alloc, 'updates) ops = + (module OPS + with type Id.t = 'id + and type alloc = 'alloc + and type updates = 'updates) + +module Sapling_state = struct + include Lazy_storage_kind.Sapling_state + + let bytes_size_for_empty = Z.of_int 33 + + let alloc ctxt ~id {memo_size} = Sapling_storage.init ctxt id ~memo_size + + let apply_updates ctxt ~id updates = + Sapling_storage.apply_diff ctxt id updates + + include Storage.Sapling +end + +(* + To add a new lazy storage kind here, you only need to create a module similar + to [Big_map] above and add a case to [get_ops] below. +*) + +let get_ops : type i a u. (i, a, u) Lazy_storage_kind.t -> (i, a, u) ops = + function + | Big_map -> + (module Big_map) + | Sapling_state -> + (module Sapling_state) + [@@coq_axiom "gadt"] + +type ('id, 'alloc) init = Existing | Copy of {src : 'id} | Alloc of 'alloc + +type ('id, 'alloc, 'updates) diff = + | Remove + | Update of {init : ('id, 'alloc) init; updates : 'updates} + +let diff_encoding : type i a u. (i, a, u) ops -> (i, a, u) diff Data_encoding.t + = + fun (module OPS) -> + let open Data_encoding in + union + [ case + (Tag 0) + ~title:"update" + (obj2 + (req "action" (constant "update")) + (req "updates" OPS.updates_encoding)) + (function + | Update {init = Existing; updates} -> Some ((), updates) | _ -> None) + (fun ((), updates) -> Update {init = Existing; updates}); + case + (Tag 1) + ~title:"remove" + (obj1 (req "action" (constant "remove"))) + (function Remove -> Some () | _ -> None) + (fun () -> Remove); + case + (Tag 2) + ~title:"copy" + (obj3 + (req "action" (constant "copy")) + (req "source" OPS.Id.encoding) + (req "updates" OPS.updates_encoding)) + (function + | Update {init = Copy {src}; updates} -> + Some ((), src, updates) + | _ -> + None) + (fun ((), src, updates) -> Update {init = Copy {src}; updates}); + case + (Tag 3) + ~title:"alloc" + (merge_objs + (obj2 + (req "action" (constant "alloc")) + (req "updates" OPS.updates_encoding)) + OPS.alloc_encoding) + (function + | Update {init = Alloc alloc; updates} -> + Some (((), updates), alloc) + | _ -> + None) + (fun (((), updates), alloc) -> Update {init = Alloc alloc; updates}) ] + +(** + [apply_updates ctxt ops ~id init] applies the updates [updates] on lazy + storage [id] on storage context [ctxt] using operations [ops] and returns the + updated storage context and the added size in bytes (may be negative). +*) +let apply_updates : + type i a u. + Raw_context.t -> + (i, a, u) ops -> + id:i -> + u -> + (Raw_context.t * Z.t) tzresult Lwt.t = + fun ctxt (module OPS) ~id updates -> + OPS.apply_updates ctxt ~id updates + >>=? fun (ctxt, updates_size) -> + if Z.(equal updates_size zero) then return (ctxt, updates_size) + else + OPS.Total_bytes.get ctxt id + >>=? fun size -> + OPS.Total_bytes.update ctxt id (Z.add size updates_size) + >|=? fun ctxt -> (ctxt, updates_size) + +(** + [apply_init ctxt ops ~id init] applies the initialization [init] on lazy + storage [id] on storage context [ctxt] using operations [ops] and returns the + updated storage context and the added size in bytes (may be negative). + + If [id] represents a temporary lazy storage, the added size may be wrong. +*) +let apply_init : + type i a u. + Raw_context.t -> + (i, a, u) ops -> + id:i -> + (i, a) init -> + (Raw_context.t * Z.t) tzresult Lwt.t = + fun ctxt (module OPS) ~id init -> + match init with + | Existing -> + return (ctxt, Z.zero) + | Copy {src} -> + OPS.copy ctxt ~from:src ~to_:id + >>=? fun ctxt -> + if OPS.Id.is_temp id then return (ctxt, Z.zero) + else + OPS.Total_bytes.get ctxt src + >>=? fun copy_size -> + return (ctxt, Z.add copy_size OPS.bytes_size_for_empty) + | Alloc alloc -> + OPS.Total_bytes.init ctxt id Z.zero + >>=? fun ctxt -> + OPS.alloc ctxt id alloc + >>=? fun ctxt -> return (ctxt, OPS.bytes_size_for_empty) + +(** + [apply_diff ctxt ops ~id diff] applies the diff [diff] on lazy storage [id] + on storage context [ctxt] using operations [ops] and returns the updated + storage context and the added size in bytes (may be negative). + + If [id] represents a temporary lazy storage, the added size may be wrong. +*) +let apply_diff : + type i a u. + Raw_context.t -> + (i, a, u) ops -> + id:i -> + (i, a, u) diff -> + (Raw_context.t * Z.t) tzresult Lwt.t = + fun ctxt ((module OPS) as ops) ~id diff -> + match diff with + | Remove -> + if OPS.Id.is_temp id then + OPS.remove ctxt id >|= fun ctxt -> ok (ctxt, Z.zero) + else + OPS.Total_bytes.get ctxt id + >>=? fun size -> + OPS.remove ctxt id + >>= fun ctxt -> + return (ctxt, Z.neg (Z.add size OPS.bytes_size_for_empty)) + | Update {init; updates} -> + apply_init ctxt ops ~id init + >>=? fun (ctxt, init_size) -> + apply_updates ctxt ops ~id updates + >>=? fun (ctxt, updates_size) -> + return (ctxt, Z.add init_size updates_size) + +type diffs_item = + | Item : + ('i, 'a, 'u) Lazy_storage_kind.t * 'i * ('i, 'a, 'u) diff + -> diffs_item + +let make : + type i a u. + (i, a, u) Lazy_storage_kind.t -> i -> (i, a, u) diff -> diffs_item = + fun k id diff -> Item (k, id, diff) + +let item_encoding = + let open Data_encoding in + union + @@ List.map + (fun (tag, Lazy_storage_kind.Ex_Kind k) -> + let ops = get_ops k in + let (module OPS) = ops in + let title = OPS.title in + case + (Tag tag) + ~title + (obj3 + (req "kind" (constant title)) + (req "id" OPS.Id.encoding) + (req "diff" (diff_encoding ops))) + (fun (Item (kind, id, diff)) -> + match Lazy_storage_kind.equal k kind with + | Eq -> + Some ((), id, diff) + | Neq -> + None) + (fun ((), id, diff) -> Item (k, id, diff))) + Lazy_storage_kind.all + [@@coq_axiom "gadt"] + +type diffs = diffs_item list + +let encoding = + let open Data_encoding in + def "lazy_storage_diff" @@ list item_encoding + +let apply ctxt diffs = + fold_left_s + (fun (ctxt, total_size) (Item (k, id, diff)) -> + let ops = get_ops k in + apply_diff ctxt ops id diff + >|=? fun (ctxt, added_size) -> + let (module OPS) = ops in + ( ctxt, + if OPS.Id.is_temp id then total_size else Z.add total_size added_size + )) + (ctxt, Z.zero) + diffs + +let fresh : + type i a u. + (i, a, u) Lazy_storage_kind.t -> + temporary:bool -> + Raw_context.t -> + (Raw_context.t * i) tzresult Lwt.t = + fun kind ~temporary ctxt -> + if temporary then + return + (Raw_context.fold_map_temporary_lazy_storage_ids ctxt (fun temp_ids -> + Lazy_storage_kind.Temp_ids.fresh kind temp_ids)) + else + let (module OPS) = get_ops kind in + OPS.Next.incr ctxt + [@@coq_axiom "gadt"] + +let init ctxt = + fold_left_s + (fun ctxt (_tag, Lazy_storage_kind.Ex_Kind k) -> + let (module OPS) = get_ops k in + OPS.Next.init ctxt) + ctxt + Lazy_storage_kind.all + [@@coq_axiom "gadt"] + +let cleanup_temporaries ctxt = + Raw_context.map_temporary_lazy_storage_ids_s ctxt (fun temp_ids -> + Lwt_list.fold_left_s + (fun ctxt (_tag, Lazy_storage_kind.Ex_Kind k) -> + let (module OPS) = get_ops k in + Lazy_storage_kind.Temp_ids.fold_s k OPS.remove temp_ids ctxt) + ctxt + Lazy_storage_kind.all + >|= fun ctxt -> (ctxt, Lazy_storage_kind.Temp_ids.init)) + [@@coq_axiom "gadt"] diff --git a/src/proto_009_PsFLoren/lib_protocol/lazy_storage_diff.mli b/src/proto_009_PsFLoren/lib_protocol/lazy_storage_diff.mli new file mode 100644 index 0000000000000000000000000000000000000000..d9ae7b42f013bcd17850d8ff9c9434edbb0e8971 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/lazy_storage_diff.mli @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining 'a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** + See [Lazy_storage_kind] for an introduction on lazy storage. + + This module defines operations on lazy storage types and diffs. +*) + +type ('id, 'alloc) init = Existing | Copy of {src : 'id} | Alloc of 'alloc + +type ('id, 'alloc, 'updates) diff = + | Remove + | Update of {init : ('id, 'alloc) init; updates : 'updates} + +(* Exposing this type is needed only for legacy big map diff. *) +type diffs_item = private + | Item : + ('i, 'a, 'u) Lazy_storage_kind.t * 'i * ('i, 'a, 'u) diff + -> diffs_item + +val make : + ('i, 'a, 'u) Lazy_storage_kind.t -> 'i -> ('i, 'a, 'u) diff -> diffs_item + +type diffs = diffs_item list + +val encoding : diffs Data_encoding.t + +(** + The returned [Z.t] is the size added by the application of the diffs. +*) +val apply : Raw_context.t -> diffs -> (Raw_context.t * Z.t) tzresult Lwt.t + +val fresh : + ('id, _, _) Lazy_storage_kind.t -> + temporary:bool -> + Raw_context.t -> + (Raw_context.t * 'id) tzresult Lwt.t + +(** + Initializes the storage for all lazy storage kind. + This is useful for genesis only. + Protocol updates need to initialize new lazy storage kinds. +*) +val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + +val cleanup_temporaries : Raw_context.t -> Raw_context.t Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/lazy_storage_kind.ml b/src/proto_009_PsFLoren/lib_protocol/lazy_storage_kind.ml new file mode 100644 index 0000000000000000000000000000000000000000..f64262eda4c1c4dad015b22ebb99f36d0b379053 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/lazy_storage_kind.ml @@ -0,0 +1,342 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type Temp_id = sig + type t + + val equal : t -> t -> bool + + val init : t + + val next : t -> t +end + +module type ID = sig + type t + + val compare : t -> t -> int + + val encoding : t Data_encoding.t + + val rpc_arg : t RPC_arg.arg + + val init : t + + (** In the protocol, to be used in parse_data only *) + val parse_z : Z.t -> t + + (** In the protocol, to be used in unparse_data only *) + val unparse_to_z : t -> Z.t + + val next : t -> t + + val is_temp : t -> bool + + val path_length : int + + val to_path : t -> string list -> string list + + val of_path : string list -> t option + + val of_legacy_USE_ONLY_IN_Legacy_big_map_diff : Z.t -> t + + val to_legacy_USE_ONLY_IN_Legacy_big_map_diff : t -> Z.t +end + +module type Title = sig + val title : string +end + +module type TitleWithId = sig + val title : string + + module Id : sig + include ID + + module Temp : Temp_id with type t = private t + end + + module IdSet : S.SET with type elt = Id.t +end + +module MakeId (Title : Title) : TitleWithId = struct + let title = Title.title + + let title_words = String.map (function '_' -> ' ' | c -> c) title + + let rpc_arg_error = Format.sprintf "Cannot parse %s id" title_words + + let description = Format.sprintf "A %s identifier" title_words + + let name = title ^ "_id" + + let encoding_title = String.capitalize_ascii title_words ^ " identifier" + + module Id = struct + type t = Z.t + + let compare = Z.compare + + let encoding = + Data_encoding.def name ~title:encoding_title ~description Data_encoding.z + + let rpc_arg = + let construct = Z.to_string in + let destruct hash = + match Z.of_string hash with + | exception _ -> + Error rpc_arg_error + | id -> + Ok id + in + RPC_arg.make ~descr:description ~name ~construct ~destruct () + + let init = Z.zero + + let parse_z (z : Z.t) : t = z + + let unparse_to_z (z : t) : Z.t = z + + let next = Z.succ + + let of_legacy_USE_ONLY_IN_Legacy_big_map_diff (z : Z.t) : t = z + + let to_legacy_USE_ONLY_IN_Legacy_big_map_diff (z : t) : Z.t = z + + module Temp = struct + type nonrec t = t + + let equal = Z.equal + + let init = Z.of_int ~-1 + + let next z = Z.sub z Z.one + end + + let is_temp z = Compare.Z.(z < Z.zero) + + let path_length = 1 + + let to_path z l = Z.to_string z :: l + + let of_path = function + | [] | _ :: _ :: _ -> + None + | [z] -> + Some (Z.of_string z) + end + + module IdSet = Set.Make (Id) +end + +module Big_map = struct + include MakeId (struct + let title = "big_map" + end) + + type alloc = {key_type : Script_repr.expr; value_type : Script_repr.expr} + + type update = { + key : Script_repr.expr; + (** The key is ignored by [apply_update] but is shown in the receipt, + as specified in [print_big_map_diff]. *) + key_hash : Script_expr_hash.t; + value : Script_repr.expr option; + } + + type updates = update list + + let alloc_encoding = + let open Data_encoding in + conv + (fun {key_type; value_type} -> (key_type, value_type)) + (fun (key_type, value_type) -> {key_type; value_type}) + (obj2 + (req "key_type" Script_repr.expr_encoding) + (req "value_type" Script_repr.expr_encoding)) + + let update_encoding = + let open Data_encoding in + conv + (fun {key_hash; key; value} -> (key_hash, key, value)) + (fun (key_hash, key, value) -> {key_hash; key; value}) + (obj3 + (req "key_hash" Script_expr_hash.encoding) + (req "key" Script_repr.expr_encoding) + (opt "value" Script_repr.expr_encoding)) + + let updates_encoding = Data_encoding.list update_encoding +end + +module Sapling_state = struct + include MakeId (struct + let title = "sapling_state" + end) + + type alloc = {memo_size : Sapling_repr.Memo_size.t} + + type updates = Sapling_repr.diff + + let alloc_encoding = + let open Data_encoding in + conv + (fun {memo_size} -> memo_size) + (fun memo_size -> {memo_size}) + (obj1 (req "memo_size" Sapling_repr.Memo_size.encoding)) + + let updates_encoding = Sapling_repr.diff_encoding +end + +(* + When adding cases to this type, grep for [new lazy storage kind] in the code + for locations to update. + It must be: + - the value [all] right below, + - modules [Temp_ids], [IdSet] below, + - the rest should be guided by type errors. +*) +type ('id, 'alloc, 'updates) t = + | Big_map : (Big_map.Id.t, Big_map.alloc, Big_map.updates) t + | Sapling_state + : (Sapling_state.Id.t, Sapling_state.alloc, Sapling_state.updates) t + +type ex = Ex_Kind : (_, _, _) t -> ex + +(* /!\ Don't forget to add new lazy storage kinds here. /!\ *) +let all = [(0, Ex_Kind Big_map); (1, Ex_Kind Sapling_state)] + +type (_, _) cmp = Eq : ('a, 'a) cmp | Neq + +let equal : + type i1 a1 u1 i2 a2 u2. + (i1, a1, u1) t -> (i2, a2, u2) t -> (i1 * a1 * u1, i2 * a2 * u2) cmp = + fun k1 k2 -> + match (k1, k2) with + | (Big_map, Big_map) -> + Eq + | (Sapling_state, Sapling_state) -> + Eq + | (Big_map, _) -> + Neq + | (_, Big_map) -> + Neq + +type ('i, 'a, 'u) kind = ('i, 'a, 'u) t + +module Temp_ids = struct + type t = { + big_map : Big_map.Id.Temp.t; + sapling_state : Sapling_state.Id.Temp.t; + } + + let init = + { + big_map = Big_map.Id.Temp.init; + sapling_state = Sapling_state.Id.Temp.init; + } + + let fresh : type i a u. (i, a, u) kind -> t -> t * i = + fun kind temp_ids -> + match kind with + | Big_map -> + let big_map = Big_map.Id.Temp.next temp_ids.big_map in + ({temp_ids with big_map}, (big_map :> Big_map.Id.t)) + | Sapling_state -> + let sapling_state = + Sapling_state.Id.Temp.next temp_ids.sapling_state + in + ({temp_ids with sapling_state}, (sapling_state :> Sapling_state.Id.t)) + [@@coq_axiom "gadt"] + + let fold_s : + type i a u. + (i, a, u) kind -> ('acc -> i -> 'acc Lwt.t) -> t -> 'acc -> 'acc Lwt.t = + fun kind f temp_ids acc -> + let helper (type j) (module Temp_id : Temp_id with type t = j) ~last f = + let rec aux acc id = + if Temp_id.equal id last then Lwt.return acc + else f acc id >>= fun acc -> aux acc (Temp_id.next id) + in + aux acc Temp_id.init + in + match kind with + | Big_map -> + helper + (module Big_map.Id.Temp) + ~last:temp_ids.big_map + (fun acc temp_id -> f acc (temp_id :> i)) + | Sapling_state -> + helper + (module Sapling_state.Id.Temp) + ~last:temp_ids.sapling_state + (fun acc temp_id -> f acc (temp_id :> i)) + [@@coq_axiom "gadt"] +end + +module IdSet = struct + type t = {big_map : Big_map.IdSet.t; sapling_state : Sapling_state.IdSet.t} + + type 'acc fold_f = {f : 'i 'a 'u. ('i, 'a, 'u) kind -> 'i -> 'acc -> 'acc} + + let empty = + {big_map = Big_map.IdSet.empty; sapling_state = Sapling_state.IdSet.empty} + + let mem (type i a u) (kind : (i, a, u) kind) (id : i) set = + match (kind, set) with + | (Big_map, {big_map}) -> + Big_map.IdSet.mem id big_map + | (Sapling_state, {sapling_state}) -> + Sapling_state.IdSet.mem id sapling_state + + let add (type i a u) (kind : (i, a, u) kind) (id : i) set = + match (kind, set) with + | (Big_map, {big_map}) -> + let big_map = Big_map.IdSet.add id big_map in + {set with big_map} + | (Sapling_state, {sapling_state}) -> + let sapling_state = Sapling_state.IdSet.add id sapling_state in + {set with sapling_state} + + let diff set1 set2 = + let big_map = Big_map.IdSet.diff set1.big_map set2.big_map in + let sapling_state = + Sapling_state.IdSet.diff set1.sapling_state set2.sapling_state + in + {big_map; sapling_state} + + let fold (type i a u) (kind : (i, a, u) kind) (f : i -> 'acc -> 'acc) set + (acc : 'acc) = + match (kind, set) with + | (Big_map, {big_map}) -> + Big_map.IdSet.fold f big_map acc + | (Sapling_state, {sapling_state}) -> + Sapling_state.IdSet.fold f sapling_state acc + + let fold_all f set acc = + List.fold_left + (fun acc (_, Ex_Kind kind) -> fold kind (f.f kind) set acc) + acc + all +end diff --git a/src/proto_009_PsFLoren/lib_protocol/lazy_storage_kind.mli b/src/proto_009_PsFLoren/lib_protocol/lazy_storage_kind.mli new file mode 100644 index 0000000000000000000000000000000000000000..70298586aa1f9c0f6834fbe36d0a8b49c6a5418c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/lazy_storage_kind.mli @@ -0,0 +1,182 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** + Lazy_storage offers a unified interface for specific Michelson datatype that + behave somewhat lazily, because they are intended to be quite big. + Instead of serializing/deserializing the whole value to/from the storage, + only an identifier is used. The identifier acts like a pointer. + When using the value in a Michelson script, some part of it may be read from + the storage, and a lightweight diff is computed. + The diff is effectively applied to the storage at the end of the execution. + + This module defines the different kinds of lazy storages and their basic + properties. See also [Lazy_storage_diff]. + + Lazy storage types are: + - Big_map +*) + +(** + Lazy storage ids are kept as abstract as possible to avoid mixing them up. + + Behind the scene they are [Z.t]s but, within the protocol, only [parse_data]/ + [unparse_data] are allowed convert from/to it. + + Temporary ids may be used to pass values between contracts that won't be kept + longer than the lifetime of the operation. + Behind the scene, temporary ids are negative [Z.t]s. +*) +module type ID = sig + type t + + val compare : t -> t -> int + + val encoding : t Data_encoding.t + + val rpc_arg : t RPC_arg.arg + + (** Initial value for ids: zero. *) + val init : t + + (** In the protocol, to be used in parse_data only *) + val parse_z : Z.t -> t + + (** In the protocol, to be used in unparse_data only *) + val unparse_to_z : t -> Z.t + + val next : t -> t + + val is_temp : t -> bool + + (* To be used in storage: *) + + val path_length : int + + val to_path : t -> string list -> string list + + val of_path : string list -> t option + + (* To be removed once legacy big map diff is removed: *) + + val of_legacy_USE_ONLY_IN_Legacy_big_map_diff : Z.t -> t + + val to_legacy_USE_ONLY_IN_Legacy_big_map_diff : t -> Z.t +end + +module Big_map : sig + val title : string + + module Id : ID + + type alloc = {key_type : Script_repr.expr; value_type : Script_repr.expr} + + type update = { + key : Script_repr.expr; + (** The key is ignored by [apply_update] but is shown in the receipt, + as specified in [print_big_map_diff]. *) + key_hash : Script_expr_hash.t; + value : Script_repr.expr option; + } + + type updates = update list + + val alloc_encoding : alloc Data_encoding.t + + val updates_encoding : updates Data_encoding.t +end + +module Sapling_state : sig + val title : string + + module Id : ID + + type alloc = {memo_size : Sapling_repr.Memo_size.t} + + type updates = Sapling_repr.diff + + val alloc_encoding : alloc Data_encoding.t + + val updates_encoding : updates Data_encoding.t +end + +(** + Kinds of lazy storage. + The GADT ensures operations are properly applied to the correct kind. + + ['id] the abstract type for the identifier of the kind. + ['alloc] is the type used to construct a new value. + ['updates] is the type used to update a value. +*) +type ('id, 'alloc, 'updates) t = + | Big_map : (Big_map.Id.t, Big_map.alloc, Big_map.updates) t + | Sapling_state + : (Sapling_state.Id.t, Sapling_state.alloc, Sapling_state.updates) t + +type ex = Ex_Kind : (_, _, _) t -> ex + +val all : (int * ex) list + +type (_, _) cmp = Eq : ('a, 'a) cmp | Neq + +val equal : + ('i1, 'a1, 'u1) t -> + ('i2, 'a2, 'u2) t -> + ('i1 * 'a1 * 'u1, 'i2 * 'a2 * 'u2) cmp + +type ('i, 'a, 'u) kind = ('i, 'a, 'u) t + +(** + Type to manage temporary ids. + Used only in the context. +*) +module Temp_ids : sig + type t + + val init : t + + val fresh : ('i, 'a, 'u) kind -> t -> t * 'i + + val fold_s : + ('i, 'a, 'u) kind -> ('acc -> 'i -> 'acc Lwt.t) -> t -> 'acc -> 'acc Lwt.t +end + +module IdSet : sig + type t + + type 'acc fold_f = {f : 'i 'a 'u. ('i, 'a, 'u) kind -> 'i -> 'acc -> 'acc} + + val empty : t + + val mem : ('i, 'a, 'u) kind -> 'i -> t -> bool + + val add : ('i, 'a, 'u) kind -> 'i -> t -> t + + val diff : t -> t -> t + + val fold : ('i, 'a, 'u) kind -> ('i -> 'acc -> 'acc) -> t -> 'acc -> 'acc + + val fold_all : 'acc fold_f -> t -> 'acc -> 'acc +end diff --git a/src/proto_009_PsFLoren/lib_protocol/level_repr.ml b/src/proto_009_PsFLoren/lib_protocol/level_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..c3aaf8aedb4b9aec0523ca375a230aa96c4ffef6 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/level_repr.ml @@ -0,0 +1,230 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + level : Raw_level_repr.t; + level_position : int32; + cycle : Cycle_repr.t; + cycle_position : int32; + expected_commitment : bool; +} + +include Compare.Make (struct + type nonrec t = t + + let compare {level = l1} {level = l2} = Raw_level_repr.compare l1 l2 +end) + +type level = t + +let pp ppf {level} = Raw_level_repr.pp ppf level + +let pp_full ppf l = + Format.fprintf + ppf + "%a.%ld (cycle %a.%ld)" + Raw_level_repr.pp + l.level + l.level_position + Cycle_repr.pp + l.cycle + l.cycle_position + +let encoding = + let open Data_encoding in + conv + (fun {level; level_position; cycle; cycle_position; expected_commitment} -> + (level, level_position, cycle, cycle_position, expected_commitment)) + (fun (level, level_position, cycle, cycle_position, expected_commitment) -> + {level; level_position; cycle; cycle_position; expected_commitment}) + (obj5 + (req + "level" + ~description: + "The level of the block relative to genesis. This is also the \ + Shell's notion of level" + Raw_level_repr.encoding) + (req + "level_position" + ~description: + "The level of the block relative to the block that starts \ + protocol alpha. This is specific to the protocol alpha. Other \ + protocols might or might not include a similar notion." + int32) + (req + "cycle" + ~description: + "The current cycle's number. Note that cycles are a \ + protocol-specific notion. As a result, the cycle number starts \ + at 0 with the first block of protocol alpha." + Cycle_repr.encoding) + (req + "cycle_position" + ~description: + "The current level of the block relative to the first block of \ + the current cycle." + int32) + (req + "expected_commitment" + ~description: + "Tells wether the baker of this block has to commit a seed nonce \ + hash." + bool)) + +let root_level first_level = + { + level = first_level; + level_position = 0l; + cycle = Cycle_repr.root; + cycle_position = 0l; + expected_commitment = false; + } + +let level_from_raw ~first_level ~blocks_per_cycle ~blocks_per_commitment level + = + let raw_level = Raw_level_repr.to_int32 level in + let first_level = Raw_level_repr.to_int32 first_level in + let level_position = + Compare.Int32.max 0l (Int32.sub raw_level first_level) + in + let cycle = + Cycle_repr.of_int32_exn (Int32.div level_position blocks_per_cycle) + in + let cycle_position = Int32.rem level_position blocks_per_cycle in + let expected_commitment = + Compare.Int32.( + Int32.rem cycle_position blocks_per_commitment + = Int32.pred blocks_per_commitment) + in + {level; level_position; cycle; cycle_position; expected_commitment} + +let diff {level = l1; _} {level = l2; _} = + Int32.sub (Raw_level_repr.to_int32 l1) (Raw_level_repr.to_int32 l2) + +type compat_t = { + level : Raw_level_repr.t; + level_position : int32; + cycle : Cycle_repr.t; + cycle_position : int32; + voting_period : int32; + voting_period_position : int32; + expected_commitment : bool; +} + +let compat_encoding = + let open Data_encoding in + conv + (fun { level; + level_position; + cycle; + cycle_position; + voting_period; + voting_period_position; + expected_commitment } -> + ( level, + level_position, + cycle, + cycle_position, + voting_period, + voting_period_position, + expected_commitment )) + (fun ( level, + level_position, + cycle, + cycle_position, + voting_period, + voting_period_position, + expected_commitment ) -> + { + level; + level_position; + cycle; + cycle_position; + voting_period; + voting_period_position; + expected_commitment; + }) + (obj7 + (req + "level" + ~description: + "The level of the block relative to genesis. This is also the \ + Shell's notion of level" + Raw_level_repr.encoding) + (req + "level_position" + ~description: + "The level of the block relative to the block that starts \ + protocol alpha. This is specific to the protocol alpha. Other \ + protocols might or might not include a similar notion." + int32) + (req + "cycle" + ~description: + "The current cycle's number. Note that cycles are a \ + protocol-specific notion. As a result, the cycle number starts \ + at 0 with the first block of protocol alpha." + Cycle_repr.encoding) + (req + "cycle_position" + ~description: + "The current level of the block relative to the first block of \ + the current cycle." + int32) + (req + "voting_period" + ~description: + "The current voting period's index. Note that cycles are a \ + protocol-specific notion. As a result, the voting period index \ + starts at 0 with the first block of protocol alpha. This field \ + is DEPRECATED: use `../votes/voting_period` RPC \ + instead." + int32) + (req + "voting_period_position" + ~description: + "The current level of the block relative to the first block of \ + the current voting period. This field is DEPRECATED: use \ + `../votes/voting_period` RPC instead." + int32) + (req + "expected_commitment" + ~description: + "Tells wether the baker of this block has to commit a seed nonce \ + hash." + bool)) + +let to_deprecated_type + ({level; level_position; cycle; cycle_position; expected_commitment} : t) + ~voting_period_index ~voting_period_position = + { + level; + level_position; + cycle; + cycle_position; + voting_period = voting_period_index; + voting_period_position; + expected_commitment; + } diff --git a/src/proto_009_PsFLoren/lib_protocol/level_repr.mli b/src/proto_009_PsFLoren/lib_protocol/level_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..1ab7137d97a660fcfc461224474385e7a849123f --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/level_repr.mli @@ -0,0 +1,87 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = private { + level : Raw_level_repr.t; + (** The level of the block relative to genesis. This + is also the Shell's notion of level. *) + level_position : int32; + (** The level of the block relative to the block that started the first + version of protocol alpha. *) + cycle : Cycle_repr.t; + (** The current cycle's number. Note that cycles are a protocol-specific + notion. As a result, the cycle number starts at 0 with the first block of + the first version of protocol alpha. *) + cycle_position : int32; + (** The current level of the block relative to the first block of the current + cycle. *) + expected_commitment : bool; +} + +(* Note that, the type `t` above must respect some invariants (hence the + `private` annotation). Notably: + + level_position = cycle * blocks_per_cycle + cycle_position +*) + +type level = t + +include Compare.S with type t := level + +val encoding : level Data_encoding.t + +val pp : Format.formatter -> level -> unit + +val pp_full : Format.formatter -> level -> unit + +val root_level : Raw_level_repr.t -> level + +val level_from_raw : + first_level:Raw_level_repr.t -> + blocks_per_cycle:int32 -> + blocks_per_commitment:int32 -> + Raw_level_repr.t -> + level + +val diff : level -> level -> int32 + +(** Compatibility module with Level_repr.t from protocol 007. + In this version, the [voting_period] and [voting_period_position] fields are + deprecated and replaced by a new RPC endpoint at + [Voting_services.voting_period] *) +type compat_t = { + level : Raw_level_repr.t; + level_position : int32; + cycle : Cycle_repr.t; + cycle_position : int32; + voting_period : int32; + voting_period_position : int32; + expected_commitment : bool; +} + +val compat_encoding : compat_t Data_encoding.t + +val to_deprecated_type : + t -> voting_period_index:int32 -> voting_period_position:int32 -> compat_t diff --git a/src/proto_009_PsFLoren/lib_protocol/level_storage.ml b/src/proto_009_PsFLoren/lib_protocol/level_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..dc3aaf9a9243de224068417e3c3efc0168918c13 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/level_storage.ml @@ -0,0 +1,117 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Level_repr + +let from_raw c ?offset l = + let l = + match offset with + | None -> + l + | Some o -> + Raw_level_repr.(of_int32_exn (Int32.add (to_int32 l) o)) + in + let constants = Raw_context.constants c in + let first_level = Raw_context.first_level c in + Level_repr.level_from_raw + ~first_level + ~blocks_per_cycle:constants.Constants_repr.blocks_per_cycle + ~blocks_per_commitment:constants.Constants_repr.blocks_per_commitment + l + +let root c = Level_repr.root_level (Raw_context.first_level c) + +let succ c (l : Level_repr.t) = from_raw c (Raw_level_repr.succ l.level) + +let pred c (l : Level_repr.t) = + match Raw_level_repr.pred l.Level_repr.level with + | None -> + None + | Some l -> + Some (from_raw c l) + +let current ctxt = Raw_context.current_level ctxt + +let previous ctxt = + let l = current ctxt in + match pred ctxt l with + | None -> + assert false (* We never validate the Genesis... *) + | Some p -> + p + +let first_level_in_cycle ctxt c = + let constants = Raw_context.constants ctxt in + let first_level = Raw_context.first_level ctxt in + from_raw + ctxt + (Raw_level_repr.of_int32_exn + (Int32.add + (Raw_level_repr.to_int32 first_level) + (Int32.mul + constants.Constants_repr.blocks_per_cycle + (Cycle_repr.to_int32 c)))) + +let last_level_in_cycle ctxt c = + match pred ctxt (first_level_in_cycle ctxt (Cycle_repr.succ c)) with + | None -> + assert false + | Some x -> + x + +let levels_in_cycle ctxt cycle = + let first = first_level_in_cycle ctxt cycle in + let rec loop (n : Level_repr.t) acc = + if Cycle_repr.(n.cycle = first.cycle) then loop (succ ctxt n) (n :: acc) + else acc + in + loop first [] + +let levels_in_current_cycle ctxt ?(offset = 0l) () = + let current_cycle = Cycle_repr.to_int32 (current ctxt).cycle in + let cycle = Int32.add current_cycle offset in + if Compare.Int32.(cycle < 0l) then [] + else + let cycle = Cycle_repr.of_int32_exn cycle in + levels_in_cycle ctxt cycle + +let levels_with_commitments_in_cycle ctxt c = + let first = first_level_in_cycle ctxt c in + let rec loop (n : Level_repr.t) acc = + if Cycle_repr.(n.cycle = first.cycle) then + if n.expected_commitment then loop (succ ctxt n) (n :: acc) + else loop (succ ctxt n) acc + else acc + in + loop first [] + +let last_allowed_fork_level c = + let level = Raw_context.current_level c in + let preserved_cycles = Constants_storage.preserved_cycles c in + match Cycle_repr.sub level.cycle preserved_cycles with + | None -> + Raw_level_repr.root + | Some cycle -> + (first_level_in_cycle c cycle).level diff --git a/src/proto_009_PsFLoren/lib_protocol/level_storage.mli b/src/proto_009_PsFLoren/lib_protocol/level_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..047fcbb40f19f9e82358bff35292930a3822e2b7 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/level_storage.mli @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val current : Raw_context.t -> Level_repr.t + +val previous : Raw_context.t -> Level_repr.t + +val root : Raw_context.t -> Level_repr.t + +val from_raw : + Raw_context.t -> ?offset:int32 -> Raw_level_repr.t -> Level_repr.t + +val pred : Raw_context.t -> Level_repr.t -> Level_repr.t option + +val succ : Raw_context.t -> Level_repr.t -> Level_repr.t + +val first_level_in_cycle : Raw_context.t -> Cycle_repr.t -> Level_repr.t + +val last_level_in_cycle : Raw_context.t -> Cycle_repr.t -> Level_repr.t + +val levels_in_cycle : Raw_context.t -> Cycle_repr.t -> Level_repr.t list + +val levels_in_current_cycle : + Raw_context.t -> ?offset:int32 -> unit -> Level_repr.t list + +val levels_with_commitments_in_cycle : + Raw_context.t -> Cycle_repr.t -> Level_repr.t list + +val last_allowed_fork_level : Raw_context.t -> Raw_level_repr.t diff --git a/src/proto_009_PsFLoren/lib_protocol/main.ml b/src/proto_009_PsFLoren/lib_protocol/main.ml new file mode 100644 index 0000000000000000000000000000000000000000..1439a430f337daeb8433ee7f0363fe32e2a58bbe --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/main.ml @@ -0,0 +1,418 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Protocol Signature Instance *) + +type block_header_data = Alpha_context.Block_header.protocol_data + +type block_header = Alpha_context.Block_header.t = { + shell : Block_header.shell_header; + protocol_data : block_header_data; +} + +let block_header_data_encoding = + Alpha_context.Block_header.protocol_data_encoding + +type block_header_metadata = Apply_results.block_metadata + +let block_header_metadata_encoding = Apply_results.block_metadata_encoding + +type operation_data = Alpha_context.packed_protocol_data = + | Operation_data : + 'kind Alpha_context.Operation.protocol_data + -> operation_data + +let operation_data_encoding = Alpha_context.Operation.protocol_data_encoding + +type operation_receipt = Apply_results.packed_operation_metadata = + | Operation_metadata : + 'kind Apply_results.operation_metadata + -> operation_receipt + | No_operation_metadata : operation_receipt + +let operation_receipt_encoding = Apply_results.operation_metadata_encoding + +let operation_data_and_receipt_encoding = + Apply_results.operation_data_and_metadata_encoding + +type operation = Alpha_context.packed_operation = { + shell : Operation.shell_header; + protocol_data : operation_data; +} + +let acceptable_passes = Alpha_context.Operation.acceptable_passes + +let max_block_length = Alpha_context.Block_header.max_header_length + +let max_operation_data_length = + Alpha_context.Constants.max_operation_data_length + +let validation_passes = + let open Alpha_context.Constants in + Updater. + [ (* 2048 endorsements *) + {max_size = 2048 * 2048; max_op = Some 2048}; + (* 32k of voting operations *) + {max_size = 32 * 1024; max_op = None}; + (* revelations, wallet activations and denunciations *) + { + max_size = max_anon_ops_per_block * 1024; + max_op = Some max_anon_ops_per_block; + }; + (* 512kB *) + {max_size = 512 * 1024; max_op = None} ] + +let rpc_services = + Alpha_services.register () ; + Services_registration.get_rpc_services () + +type validation_mode = + | Application of { + block_header : Alpha_context.Block_header.t; + baker : Alpha_context.public_key_hash; + block_delay : Alpha_context.Period.t; + } + | Partial_application of { + block_header : Alpha_context.Block_header.t; + baker : Alpha_context.public_key_hash; + block_delay : Alpha_context.Period.t; + } + | Partial_construction of {predecessor : Block_hash.t} + | Full_construction of { + predecessor : Block_hash.t; + protocol_data : Alpha_context.Block_header.contents; + baker : Alpha_context.public_key_hash; + block_delay : Alpha_context.Period.t; + } + +type validation_state = { + mode : validation_mode; + chain_id : Chain_id.t; + ctxt : Alpha_context.t; + op_count : int; + migration_balance_updates : Alpha_context.Receipt.balance_updates; +} + +let current_context {ctxt; _} = return (Alpha_context.finalize ctxt).context + +let begin_partial_application ~chain_id ~ancestor_context:ctxt + ~predecessor_timestamp ~predecessor_fitness + (block_header : Alpha_context.Block_header.t) = + let level = block_header.shell.level in + let fitness = predecessor_fitness in + let timestamp = block_header.shell.timestamp in + Alpha_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt + >>=? fun (ctxt, migration_balance_updates) -> + Apply.begin_application ctxt chain_id block_header predecessor_timestamp + >|=? fun (ctxt, baker, block_delay) -> + let mode = + Partial_application + {block_header; baker = Signature.Public_key.hash baker; block_delay} + in + {mode; chain_id; ctxt; op_count = 0; migration_balance_updates} + +let begin_application ~chain_id ~predecessor_context:ctxt + ~predecessor_timestamp ~predecessor_fitness + (block_header : Alpha_context.Block_header.t) = + let level = block_header.shell.level in + let fitness = predecessor_fitness in + let timestamp = block_header.shell.timestamp in + Alpha_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt + >>=? fun (ctxt, migration_balance_updates) -> + Apply.begin_application ctxt chain_id block_header predecessor_timestamp + >|=? fun (ctxt, baker, block_delay) -> + let mode = + Application + {block_header; baker = Signature.Public_key.hash baker; block_delay} + in + {mode; chain_id; ctxt; op_count = 0; migration_balance_updates} + +let begin_construction ~chain_id ~predecessor_context:ctxt + ~predecessor_timestamp ~predecessor_level:pred_level + ~predecessor_fitness:pred_fitness ~predecessor ~timestamp + ?(protocol_data : block_header_data option) () = + let level = Int32.succ pred_level in + let fitness = pred_fitness in + Alpha_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt + >>=? fun (ctxt, migration_balance_updates) -> + ( match protocol_data with + | None -> + Apply.begin_partial_construction ctxt + >|=? fun ctxt -> + let mode = Partial_construction {predecessor} in + (mode, ctxt) + | Some proto_header -> + Apply.begin_full_construction + ctxt + predecessor_timestamp + proto_header.contents + >|=? fun (ctxt, protocol_data, baker, block_delay) -> + let mode = + let baker = Signature.Public_key.hash baker in + Full_construction {predecessor; baker; protocol_data; block_delay} + in + (mode, ctxt) ) + >|=? fun (mode, ctxt) -> + {mode; chain_id; ctxt; op_count = 0; migration_balance_updates} + +let apply_operation ({mode; chain_id; ctxt; op_count; _} as data) + (operation : Alpha_context.packed_operation) = + match mode with + | Partial_application _ + when not + (List.exists + (Compare.Int.equal 0) + (Alpha_context.Operation.acceptable_passes operation)) -> + (* Multipass validation only considers operations in pass 0. *) + let op_count = op_count + 1 in + return ({data with ctxt; op_count}, No_operation_metadata) + | _ -> + let {shell; protocol_data = Operation_data protocol_data} = operation in + let operation : _ Alpha_context.operation = {shell; protocol_data} in + let (predecessor, baker) = + match mode with + | Partial_application + {block_header = {shell = {predecessor; _}; _}; baker} + | Application {block_header = {shell = {predecessor; _}; _}; baker} + | Full_construction {predecessor; baker; _} -> + (predecessor, baker) + | Partial_construction {predecessor} -> + (predecessor, Signature.Public_key_hash.zero) + in + Apply.apply_operation + ctxt + chain_id + Optimized + predecessor + baker + (Alpha_context.Operation.hash operation) + operation + >|=? fun (ctxt, result) -> + let op_count = op_count + 1 in + ({data with ctxt; op_count}, Operation_metadata result) + +let finalize_block {mode; ctxt; op_count; migration_balance_updates} = + match mode with + | Partial_construction _ -> + Alpha_context.Voting_period.get_current_info ctxt + >>=? fun {voting_period = {kind; _}; _} -> + Alpha_context.Voting_period.get_rpc_fixed_current_info ctxt + >>=? fun ({voting_period; position; _} as voting_period_info) -> + let level_info = Alpha_context.Level.current ctxt in + let baker = Signature.Public_key_hash.zero in + Signature.Public_key_hash.Map.fold + (fun delegate deposit ctxt -> + ctxt + >>=? fun ctxt -> + Alpha_context.Delegate.freeze_deposit ctxt delegate deposit) + (Alpha_context.get_deposits ctxt) + (return ctxt) + >|=? fun ctxt -> + let ctxt = Alpha_context.finalize ctxt in + ( ctxt, + Apply_results. + { + baker; + level = + Alpha_context.Level.to_deprecated_type + level_info + ~voting_period_index:voting_period.index + ~voting_period_position:position; + level_info; + voting_period_kind = kind; + voting_period_info; + nonce_hash = None; + consumed_gas = Alpha_context.Gas.Arith.zero; + deactivated = []; + balance_updates = migration_balance_updates; + } ) + | Partial_application {block_header; baker; block_delay} -> + let included_endorsements = Alpha_context.included_endorsements ctxt in + Apply.check_minimum_endorsements + ctxt + block_header.protocol_data.contents + block_delay + included_endorsements + >>?= fun () -> + Alpha_context.Voting_period.get_current_info ctxt + >>=? fun {voting_period = {kind; _}; _} -> + Alpha_context.Voting_period.get_rpc_fixed_current_info ctxt + >|=? fun ({voting_period; position; _} as voting_period_info) -> + let level_info = Alpha_context.Level.current ctxt in + let ctxt = Alpha_context.finalize ctxt in + ( ctxt, + Apply_results. + { + baker; + level = + Alpha_context.Level.to_deprecated_type + level_info + ~voting_period_index:voting_period.index + ~voting_period_position:position; + level_info; + voting_period_kind = kind; + voting_period_info; + nonce_hash = None; + consumed_gas = Alpha_context.Gas.Arith.zero; + deactivated = []; + balance_updates = migration_balance_updates; + } ) + | Application + { baker; + block_delay; + block_header = {protocol_data = {contents = protocol_data; _}; _} } + | Full_construction {protocol_data; baker; block_delay; _} -> + Apply.finalize_application + ctxt + protocol_data + baker + ~block_delay + migration_balance_updates + >|=? fun (ctxt, receipt) -> + let level = Alpha_context.Level.current ctxt in + let priority = protocol_data.priority in + let raw_level = Alpha_context.Raw_level.to_int32 level.level in + let fitness = Alpha_context.Fitness.current ctxt in + let commit_message = + Format.asprintf + "lvl %ld, fit 1:%Ld, prio %d, %d ops" + raw_level + fitness + priority + op_count + in + let ctxt = Alpha_context.finalize ~commit_message ctxt in + (ctxt, receipt) + +let compare_operations op1 op2 = + let open Alpha_context in + let (Operation_data op1) = op1.protocol_data in + let (Operation_data op2) = op2.protocol_data in + match (op1.contents, op2.contents) with + | (Single (Endorsement _), Single (Endorsement _)) -> + 0 + | (_, Single (Endorsement _)) -> + 1 + | (Single (Endorsement _), _) -> + -1 + | (Single (Seed_nonce_revelation _), Single (Seed_nonce_revelation _)) -> + 0 + | (_, Single (Seed_nonce_revelation _)) -> + 1 + | (Single (Seed_nonce_revelation _), _) -> + -1 + | ( Single (Double_endorsement_evidence _), + Single (Double_endorsement_evidence _) ) -> + 0 + | (_, Single (Double_endorsement_evidence _)) -> + 1 + | (Single (Double_endorsement_evidence _), _) -> + -1 + | (Single (Endorsement_with_slot _), Single (Endorsement_with_slot _)) -> + 0 + | (_, Single (Endorsement_with_slot _)) -> + 1 + | (Single (Endorsement_with_slot _), _) -> + -1 + | (Single (Double_baking_evidence _), Single (Double_baking_evidence _)) -> + 0 + | (_, Single (Double_baking_evidence _)) -> + 1 + | (Single (Double_baking_evidence _), _) -> + -1 + | (Single (Activate_account _), Single (Activate_account _)) -> + 0 + | (_, Single (Activate_account _)) -> + 1 + | (Single (Activate_account _), _) -> + -1 + | (Single (Proposals _), Single (Proposals _)) -> + 0 + | (_, Single (Proposals _)) -> + 1 + | (Single (Proposals _), _) -> + -1 + | (Single (Ballot _), Single (Ballot _)) -> + 0 + | (_, Single (Ballot _)) -> + 1 + | (Single (Ballot _), _) -> + -1 + | (Single (Failing_noop _), Single (Failing_noop _)) -> + 0 + | (_, Single (Failing_noop _)) -> + 1 + | (Single (Failing_noop _), _) -> + -1 + (* Manager operations with smaller counter are pre-validated first. *) + | (Single (Manager_operation op1), Single (Manager_operation op2)) -> + Z.compare op1.counter op2.counter + | (Cons (Manager_operation op1, _), Single (Manager_operation op2)) -> + Z.compare op1.counter op2.counter + | (Single (Manager_operation op1), Cons (Manager_operation op2, _)) -> + Z.compare op1.counter op2.counter + | (Cons (Manager_operation op1, _), Cons (Manager_operation op2, _)) -> + Z.compare op1.counter op2.counter + +let init ctxt block_header = + let level = block_header.Block_header.level in + let fitness = block_header.fitness in + let timestamp = block_header.timestamp in + let typecheck (ctxt : Alpha_context.context) + (script : Alpha_context.Script.t) = + let allow_forged_in_storage = + false + (* There should be no forged value in bootstrap contracts. *) + in + Script_ir_translator.parse_script + ctxt + ~legacy:false + ~allow_forged_in_storage + script + >>=? fun (Ex_script parsed_script, ctxt) -> + Script_ir_translator.extract_lazy_storage_diff + ctxt + Optimized + parsed_script.storage_type + parsed_script.storage + ~to_duplicate:Script_ir_translator.no_lazy_storage_id + ~to_update:Script_ir_translator.no_lazy_storage_id + ~temporary:false + >>=? fun (storage, lazy_storage_diff, ctxt) -> + Script_ir_translator.unparse_data + ctxt + Optimized + parsed_script.storage_type + storage + >|=? fun (storage, ctxt) -> + let storage = + Alpha_context.Script.lazy_expr (Micheline.strip_locations storage) + in + (({script with storage}, lazy_storage_diff), ctxt) + in + Alpha_context.prepare_first_block ~typecheck ~level ~timestamp ~fitness ctxt + >|=? fun ctxt -> Alpha_context.finalize ctxt + +(* Vanity nonce: 0000006957234545 *) diff --git a/src/proto_009_PsFLoren/lib_protocol/main.mli b/src/proto_009_PsFLoren/lib_protocol/main.mli new file mode 100644 index 0000000000000000000000000000000000000000..2128db498b606ca30cc935460250224df5823a25 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/main.mli @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Protocol Signature Instance *) + +type validation_mode = + | Application of { + block_header : Alpha_context.Block_header.t; + baker : Alpha_context.public_key_hash; + block_delay : Alpha_context.Period.t; + } + | Partial_application of { + block_header : Alpha_context.Block_header.t; + baker : Alpha_context.public_key_hash; + block_delay : Alpha_context.Period.t; + } + | Partial_construction of {predecessor : Block_hash.t} + | Full_construction of { + predecessor : Block_hash.t; + protocol_data : Alpha_context.Block_header.contents; + baker : Alpha_context.public_key_hash; + block_delay : Alpha_context.Period.t; + } + +type validation_state = { + mode : validation_mode; + chain_id : Chain_id.t; + ctxt : Alpha_context.t; + op_count : int; + migration_balance_updates : Alpha_context.Receipt.balance_updates; +} + +type operation_data = Alpha_context.packed_protocol_data + +type operation = Alpha_context.packed_operation = { + shell : Operation.shell_header; + protocol_data : operation_data; +} + +include + Updater.PROTOCOL + with type block_header_data = Alpha_context.Block_header.protocol_data + and type block_header_metadata = Apply_results.block_metadata + and type block_header = Alpha_context.Block_header.t + and type operation_data := operation_data + and type operation_receipt = Apply_results.packed_operation_metadata + and type operation := operation + and type validation_state := validation_state diff --git a/src/proto_009_PsFLoren/lib_protocol/manager_repr.ml b/src/proto_009_PsFLoren/lib_protocol/manager_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..b96a51401289eda7253721bd00572bce6009070a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/manager_repr.ml @@ -0,0 +1,52 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Low level Repr. of Managers' keys *) + +type manager_key = + | Hash of Signature.Public_key_hash.t + | Public_key of Signature.Public_key.t + +type t = manager_key + +open Data_encoding + +let hash_case tag = + case + tag + ~title:"Public_key_hash" + Signature.Public_key_hash.encoding + (function Hash hash -> Some hash | _ -> None) + (fun hash -> Hash hash) + +let pubkey_case tag = + case + tag + ~title:"Public_key" + Signature.Public_key.encoding + (function Public_key hash -> Some hash | _ -> None) + (fun hash -> Public_key hash) + +let encoding = union [hash_case (Tag 0); pubkey_case (Tag 1)] diff --git a/src/proto_009_PsFLoren/lib_protocol/manager_repr.mli b/src/proto_009_PsFLoren/lib_protocol/manager_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..18ca236d71b1b3bd1b7c643078ecfbe9a34b4499 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/manager_repr.mli @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Low level Repr. of Managers' keys *) + +(** The public key of the manager of a contract is reveled only after the + first operation. At Origination time, the manager provides only the hash + of its public key that is stored in the contract. When the public key + is actually revealed, the public key instead of the hash of the key *) +type manager_key = + | Hash of Signature.Public_key_hash.t + | Public_key of Signature.Public_key.t + +type t = manager_key + +val encoding : t Data_encoding.encoding diff --git a/src/proto_009_PsFLoren/lib_protocol/michelson_v1_gas.ml b/src/proto_009_PsFLoren/lib_protocol/michelson_v1_gas.ml new file mode 100644 index 0000000000000000000000000000000000000000..98e5b0b7c485eceef7beb79a111b53aa334fca65 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/michelson_v1_gas.ml @@ -0,0 +1,1489 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Gas +module S = Saturation_repr + +module Cost_of = struct + module S_syntax = struct + (* This is a good enough approximation. S.numbits 0 = 0 *) + let log2 x = S.safe_int (1 + Z.numbits (S.to_z x)) + + let ( + ) = S.add + + let ( * ) = S.mul + + let ( lsr ) = S.shift_right + end + + let z_bytes (z : Z.t) = + let bits = Z.numbits z in + (7 + bits) / 8 + + let int_bytes (z : 'a Script_int.num) = z_bytes (Script_int.to_zint z) + + let timestamp_bytes (t : Script_timestamp.t) = + let z = Script_timestamp.to_zint t in + z_bytes z + + (* Upper-bound on the time to compare the given value. + For now, returns size in bytes, but this could get more complicated... *) + let rec size_of_comparable : + type a. a Script_typed_ir.comparable_ty -> a -> S.may_saturate S.t = + fun wit v -> + match (wit, v) with + | (Unit_key _, _) -> + S.safe_int 1 + | (Never_key _, _) -> + . + | (Int_key _, _) -> + S.safe_int @@ int_bytes v + | (Nat_key _, _) -> + S.safe_int @@ int_bytes v + | (Signature_key _, _) -> + S.safe_int Signature.size + | (String_key _, _) -> + S.safe_int @@ String.length v + | (Bytes_key _, _) -> + S.safe_int @@ Bytes.length v + | (Bool_key _, _) -> + S.safe_int 8 + | (Key_hash_key _, _) -> + S.safe_int Signature.Public_key_hash.size + | (Key_key _, k) -> + S.safe_int @@ Signature.Public_key.size k + | (Timestamp_key _, _) -> + S.safe_int @@ timestamp_bytes v + | (Address_key _, _) -> + S.safe_int Signature.Public_key_hash.size + | (Mutez_key _, _) -> + S.safe_int 8 + | (Chain_id_key _, _) -> + S.safe_int Chain_id.size + | (Pair_key ((l, _), (r, _), _), (lval, rval)) -> + S.add (size_of_comparable l lval) (size_of_comparable r rval) + | (Union_key ((t, _), _, _), L x) -> + S.add (S.safe_int 1) (size_of_comparable t x) + | (Union_key (_, (t, _), _), R x) -> + S.add (S.safe_int 1) (size_of_comparable t x) + | (Option_key _, None) -> + S.safe_int 1 + | (Option_key (t, _), Some x) -> + S.add (S.safe_int 1) (size_of_comparable t x) + + let manager_operation = step_cost @@ S.safe_int 1_000 + + (* FIXME: hardcoded constant, available in next environment version. + Set to a reasonable upper bound. *) + let public_key_size = 64 + + module Generated_costs_007 = struct + (* Automatically generated costs functions. *) + + (* model N_Abs_int *) + (* Approximating 0.068306 x term *) + let cost_N_Abs_int size = S.safe_int @@ (80 + (size lsr 4)) + + (* model N_Add_bls12_381_fr *) + + let cost_N_Add_bls12_381_fr = S.safe_int 200 + + (* model N_Add_bls12_381_g1 *) + + let cost_N_Add_bls12_381_g1 = S.safe_int 8_300 + + (* model N_Add_bls12_381_g2 *) + + let cost_N_Add_bls12_381_g2 = S.safe_int 11_450 + + (* model N_Add_intint *) + (* Approximating 0.082158 x term *) + let cost_N_Add_intint size1 size2 = + let v0 = Compare.Int.max size1 size2 in + S.safe_int (80 + ((v0 lsr 4) + (v0 lsr 6))) + + (* model N_Add_tez *) + let cost_N_Add_tez = S.safe_int 55 + + (* model N_And *) + let cost_N_And = S.safe_int 50 + + (* model N_And_nat *) + (* Approximating 0.079325 x term *) + let cost_N_And_nat size1 size2 = + let v0 = Compare.Int.min size1 size2 in + S.safe_int (80 + ((v0 lsr 4) + (v0 lsr 6))) + + (* model N_Blake2b *) + (* Approximating 1.366428 x term *) + let cost_N_Blake2b size = + let open S_syntax in + let size = S.safe_int size in + S.safe_int 500 + (size + (size lsr 2)) + + (* model N_Car *) + let cost_N_Car = S.safe_int 50 + + (* model N_Cdr *) + let cost_N_Cdr = S.safe_int 50 + + (* model N_Check_signature_ed25519 *) + (* Approximating 1.372685 x term *) + let cost_N_Check_signature_ed25519 size = + let open S_syntax in + let size = S.safe_int size in + S.safe_int 270_000 + (size + (size lsr 2)) + + (* model N_Check_signature_p256 *) + (* Approximating 1.385771 x term *) + let cost_N_Check_signature_p256 size = + let open S_syntax in + let size = S.safe_int size in + S.safe_int 600_000 + (size + (size lsr 2) + (size lsr 3)) + + (* model N_Check_signature_secp256k1 *) + (* Approximating 1.372411 x term *) + let cost_N_Check_signature_secp256k1 size = + let open S_syntax in + let size = S.safe_int size in + S.safe_int 60_000 + (size + (size lsr 2)) + + (* model N_Comb *) + (* Approximating 3.275337 x term *) + let cost_N_Comb size = S.safe_int (80 + ((3 * size) + (size lsr 2))) + + (* model N_Comb_get *) + (* Approximating 0.553178 x term *) + let cost_N_Comb_get size = S.safe_int (80 + ((size lsr 1) + (size lsr 4))) + + (* model N_Comb_set *) + (* Approximating 1.282976 x term *) + let cost_N_Comb_set size = S.safe_int (80 + (size + (size lsr 2))) + + (* model N_Compare_address *) + let cost_N_Compare_address size1 size2 = + S.safe_int (80 + (2 * Compare.Int.min size1 size2)) + + (* model N_Compare_bool *) + let cost_N_Compare_bool size1 size2 = + S.safe_int (80 + (128 * Compare.Int.min size1 size2)) + + (* model N_Compare_int *) + (* Approximating 0.073657 x term *) + let cost_N_Compare_int size1 size2 = + let v0 = Compare.Int.min size1 size2 in + S.safe_int (150 + ((v0 lsr 4) + (v0 lsr 7))) + + (* model N_Compare_key_hash *) + let cost_N_Compare_key_hash size1 size2 = + S.safe_int (80 + (2 * Compare.Int.min size1 size2)) + + (* model N_Compare_mutez *) + let cost_N_Compare_mutez size1 size2 = + S.safe_int (13 * Compare.Int.min size1 size2) + + (* model N_Compare_string *) + (* Approximating 0.039389 x term *) + let cost_N_Compare_string size1 size2 = + let v0 = Compare.Int.min size1 size2 in + S.safe_int (120 + ((v0 lsr 5) + (v0 lsr 7))) + + (* model N_Compare_timestamp *) + (* Approximating 0.072483 x term *) + let cost_N_Compare_timestamp size1 size2 = + let v0 = Compare.Int.min size1 size2 in + S.safe_int (140 + ((v0 lsr 4) + (v0 lsr 7))) + + (* model N_Concat_string_pair *) + (* Approximating 0.068808 x term *) + let cost_N_Concat_string_pair size1 size2 = + let open S_syntax in + let v0 = S.safe_int size1 + S.safe_int size2 in + S.safe_int 80 + (v0 lsr 4) + + (* model N_Cons_list *) + let cost_N_Cons_list = S.safe_int 50 + + (* model N_Cons_none *) + let cost_N_Cons_none = S.safe_int 45 + + (* model N_Cons_pair *) + let cost_N_Cons_pair = S.safe_int 45 + + (* model N_Cons_some *) + let cost_N_Cons_some = S.safe_int 45 + + (* model N_Const *) + let cost_N_Const = S.safe_int 45 + + (* model N_Dig *) + let cost_N_Dig size = S.safe_int (100 + (4 * size)) + + (* model N_Dip *) + let cost_N_Dip = S.safe_int 45 + + (* model N_DipN *) + let cost_N_DipN size = S.safe_int (100 + (4 * size)) + + (* model N_Drop *) + let cost_N_Drop = S.safe_int 45 + + (* model N_DropN *) + let cost_N_DropN size = S.safe_int (100 + (4 * size)) + + (* model N_Dug *) + let cost_N_Dug size = S.safe_int (100 + (4 * size)) + + (* model N_Dup *) + let cost_N_Dup = S.safe_int 50 + + (* model N_DupN *) + (* Approximating 1.299969 x term *) + let cost_N_DupN size = S.safe_int (60 + size + (size lsr 2)) + + (* model N_Ediv_natnat *) + (* Approximating 0.001599 x term *) + let cost_N_Ediv_natnat size1 size2 = + let q = size1 - size2 in + if Compare.Int.(q < 0) then S.safe_int 300 + else + let open S_syntax in + let v0 = S.safe_int q * S.safe_int size2 in + S.safe_int 300 + (v0 lsr 10) + (v0 lsr 11) + (v0 lsr 13) + + (* model N_Ediv_tez *) + let cost_N_Ediv_tez = S.safe_int 200 + + (* model N_Ediv_teznat *) + (* Extracted by hand from the empirical data *) + let cost_N_Ediv_teznat = S.safe_int 300 + + (* model N_Empty_map *) + let cost_N_Empty_map = S.safe_int 200 + + (* model N_Empty_set *) + let cost_N_Empty_set = S.safe_int 200 + + (* model N_Eq *) + let cost_N_Eq = S.safe_int 50 + + (* model N_If *) + let cost_N_If = S.safe_int 25 + + (* model N_If_cons *) + let cost_N_If_cons = S.safe_int 30 + + (* model N_If_left *) + let cost_N_If_left = S.safe_int 30 + + (* model N_If_none *) + let cost_N_If_none = S.safe_int 30 + + (* model N_Int_nat *) + let cost_N_Int_nat = S.safe_int 45 + + (* model N_Is_nat *) + let cost_N_Is_nat = S.safe_int 50 + + (* model N_Keccak *) + let cost_N_Keccak size = + let open S_syntax in + S.safe_int 1_400 + (S.safe_int 30 * S.safe_int size) + + (* model N_Left *) + let cost_N_Left = S.safe_int 45 + + (* model N_List_iter *) + let cost_N_List_iter size = + let open S_syntax in + S.safe_int 500 + (S.safe_int 7 * S.safe_int size) + + (* model N_List_map *) + let cost_N_List_map size = + let open S_syntax in + S.safe_int 500 + (S.safe_int 12 * S.safe_int size) + + (* model N_List_size *) + let cost_N_List_size = S.safe_int 50 + + (* model N_Loop *) + let cost_N_Loop = S.safe_int 40 + + (* model N_Loop_left *) + let cost_N_Loop_left = S.safe_int 45 + + (* model N_Lsl_nat *) + (* Approximating 0.129443 x term *) + let cost_N_Lsl_nat size = S.safe_int (150 + (size lsr 3)) + + (* model N_Lsr_nat *) + (* Approximating 0.129435 x term *) + let cost_N_Lsr_nat size = S.safe_int (150 + (size lsr 3)) + + (* model N_Map_get *) + (* Approximating 0.057548 x term *) + let cost_N_Map_get size1 size2 = + let open S_syntax in + let v0 = size1 * log2 size2 in + S.safe_int 80 + (v0 lsr 5) + (v0 lsr 6) + (v0 lsr 7) + + (* model N_Map_iter *) + let cost_N_Map_iter size = + let open S_syntax in + S.safe_int 80 + (S.safe_int 40 * S.safe_int size) + + (* model N_Map_map *) + let cost_N_Map_map size = + let open S_syntax in + S.safe_int 80 + (S.safe_int 761 * S.safe_int size) + + (* model N_Map_mem *) + (* Approximating 0.058563 x term *) + let cost_N_Map_mem size1 size2 = + let open S_syntax in + let v0 = size1 * log2 size2 in + S.safe_int 80 + (v0 lsr 5) + (v0 lsr 6) + (v0 lsr 7) + + (* model N_Map_size *) + let cost_N_Map_size = S.safe_int 50 + + (* model N_Map_update *) + (* Approximating 0.119968 x term *) + let cost_N_Map_update size1 size2 = + let open S_syntax in + let v0 = size1 * log2 size2 in + S.safe_int 80 + (v0 lsr 4) + (v0 lsr 5) + (v0 lsr 6) + (v0 lsr 7) + + (* model N_Mul_bls12_381_fr *) + + let cost_N_Mul_bls12_381_fr = S.safe_int 250 + + (* model N_Mul_bls12_381_g1 *) + + let cost_N_Mul_bls12_381_g1 = S.safe_int 242_000 + + (* model N_Mul_bls12_381_g2 *) + + let cost_N_Mul_bls12_381_g2 = S.safe_int 785_500 + + (* Converting fr from/to S.t *) + let cost_bls12_381_fr_of_z = S.safe_int 130 + + let cost_bls12_381_fr_to_z = S.safe_int 30 + + let cost_N_Mul_bls12_381_fr_z = + S.add cost_bls12_381_fr_of_z cost_N_Mul_bls12_381_fr + + let cost_N_Int_bls12_381_fr = cost_bls12_381_fr_to_z + + (* model N_Mul_intint *) + let cost_N_Mul_intint size1 size2 = + let open S_syntax in + let a = S.add (S.safe_int size1) (S.safe_int size2) in + S.safe_int 80 + (a * log2 a) + + (* model N_Mul_teznat *) + let cost_N_Mul_teznat size = + let open S_syntax in + S.safe_int 200 + (S.safe_int 133 * S.safe_int size) + + (* model N_Neg_bls12_381_fr *) + + let cost_N_Neg_bls12_381_fr = S.safe_int 150 + + (* model N_Neg_bls12_381_g1 *) + + let cost_N_Neg_bls12_381_g1 = S.safe_int 350 + + (* model N_Neg_bls12_381_g2 *) + + let cost_N_Neg_bls12_381_g2 = S.safe_int 600 + + (* model N_Neg_int *) + (* Approximating 0.068419 x term *) + let cost_N_Neg_int size = S.safe_int (80 + (size lsr 4)) + + (* model N_Neq *) + let cost_N_Neq = S.safe_int 45 + + (* model N_Nil *) + let cost_N_Nil = S.safe_int 45 + + (* model N_Nop *) + let cost_N_Nop = S.safe_int 45 + + (* model N_Not *) + let cost_N_Not = S.safe_int 50 + + (* model N_Not_int *) + (* Approximating 0.076564 x term *) + let cost_N_Not_int size = S.safe_int (55 + ((size lsr 4) + (size lsr 7))) + + (* model N_Or *) + let cost_N_Or = S.safe_int 50 + + (* model N_Or_nat *) + (* Approximating 0.078718 x term *) + let cost_N_Or_nat size1 size2 = + let v0 = Compare.Int.max size1 size2 in + S.safe_int (80 + ((v0 lsr 4) + (v0 lsr 6))) + + (* model N_Pairing_check_bls12_381 *) + + let cost_N_Pairing_check_bls12_381 size = + S.add + (S.safe_int 1_550_000) + (S.mul (S.safe_int 510_000) (S.safe_int size)) + + (* model N_Right *) + let cost_N_Right = S.safe_int 45 + + (* model N_Seq *) + let cost_N_Seq = S.safe_int 30 + + (* model N_Set_iter *) + let cost_N_Set_iter size = + let open S_syntax in + S.safe_int 80 + (S.safe_int 36 * S.safe_int size) + + (* model N_Set_mem *) + (* Approximating 0.059410 x term *) + let cost_N_Set_mem size1 size2 = + let open S_syntax in + let v0 = size1 * log2 (S.safe_int size2) in + S.safe_int 80 + (v0 lsr 5) + (v0 lsr 6) + (v0 lsr 7) + (v0 lsr 8) + + (* model N_Set_size *) + let cost_N_Set_size = S.safe_int 50 + + (* model N_Set_update *) + (* Approximating 0.126260 x term *) + let cost_N_Set_update size1 size2 = + let open S_syntax in + let v0 = size1 * log2 (S.safe_int size2) in + S.safe_int 80 + (v0 lsr 3) + + (* model N_Sha256 *) + let cost_N_Sha256 size = + let open S_syntax in + S.safe_int 500 + (S.safe_int 5 * S.safe_int size) + + (* model N_Sha3 *) + let cost_N_Sha3 size = + let open S_syntax in + S.safe_int 1_400 + (S.safe_int 32 * S.safe_int size) + + (* model N_Sha512 *) + let cost_N_Sha512 size = + let open S_syntax in + S.safe_int 500 + (S.safe_int 3 * S.safe_int size) + + (* model N_Slice_string *) + (* Approximating 0.067048 x term *) + let cost_N_Slice_string size = S.safe_int (80 + (size lsr 4)) + + (* model N_String_size *) + let cost_N_String_size = S.safe_int 50 + + (* model N_Sub_int *) + (* Approximating 0.082399 x term *) + let cost_N_Sub_int size1 size2 = + let v0 = Compare.Int.max size1 size2 in + S.safe_int (80 + ((v0 lsr 4) + (v0 lsr 6))) + + (* model N_Sub_tez *) + let cost_N_Sub_tez = S.safe_int 55 + + (* model N_Swap *) + let cost_N_Swap = S.safe_int 40 + + (* model N_Total_voting_power *) + let cost_N_Total_voting_power = S.safe_int 400 + + (* model N_Uncomb *) + (* Approximating 3.666332 x term *) + let cost_N_Uncomb size = + S.safe_int (80 + ((3 * size) + (size lsr 1) + (size lsr 3))) + + (* model N_Unpair *) + let cost_N_Unpair = S.safe_int 50 + + (* model N_Voting_power *) + let cost_N_Voting_power = S.safe_int 400 + + (* model N_Xor *) + let cost_N_Xor = S.safe_int 50 + + (* model N_Xor_nat *) + (* Approximating 0.078258 x term *) + let cost_N_Xor_nat size1 size2 = + let v0 = Compare.Int.max size1 size2 in + S.safe_int (80 + ((v0 lsr 4) + (v0 lsr 6))) + + (* model DECODING_BLS_FR *) + + let cost_DECODING_BLS_FR = S.safe_int 50 + + (* model DECODING_BLS_G1 *) + + let cost_DECODING_BLS_G1 = S.safe_int 230_000 + + (* model DECODING_BLS_G2 *) + + let cost_DECODING_BLS_G2 = S.safe_int 740_000 + + (* model B58CHECK_DECODING_CHAIN_ID *) + let cost_B58CHECK_DECODING_CHAIN_ID = S.safe_int 1_500 + + (* model B58CHECK_DECODING_PUBLIC_KEY_HASH_ed25519 *) + let cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_ed25519 = S.safe_int 3_300 + + (* model B58CHECK_DECODING_PUBLIC_KEY_HASH_p256 *) + let cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_p256 = S.safe_int 3_300 + + (* model B58CHECK_DECODING_PUBLIC_KEY_HASH_secp256k1 *) + let cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_secp256k1 = S.safe_int 3_300 + + (* model B58CHECK_DECODING_PUBLIC_KEY_ed25519 *) + let cost_B58CHECK_DECODING_PUBLIC_KEY_ed25519 = S.safe_int 4_300 + + (* model B58CHECK_DECODING_PUBLIC_KEY_p256 *) + let cost_B58CHECK_DECODING_PUBLIC_KEY_p256 = S.safe_int 29_000 + + (* model B58CHECK_DECODING_PUBLIC_KEY_secp256k1 *) + let cost_B58CHECK_DECODING_PUBLIC_KEY_secp256k1 = S.safe_int 9_400 + + (* model B58CHECK_DECODING_SIGNATURE_ed25519 *) + let cost_B58CHECK_DECODING_SIGNATURE_ed25519 = S.safe_int 6_600 + + (* model B58CHECK_DECODING_SIGNATURE_p256 *) + let cost_B58CHECK_DECODING_SIGNATURE_p256 = S.safe_int 6_600 + + (* model B58CHECK_DECODING_SIGNATURE_secp256k1 *) + let cost_B58CHECK_DECODING_SIGNATURE_secp256k1 = S.safe_int 6_600 + + (* model ENCODING_BLS_FR *) + + let cost_ENCODING_BLS_FR = S.safe_int 30 + + (* model ENCODING_BLS_G1 *) + + let cost_ENCODING_BLS_G1 = S.safe_int 30 + + (* model ENCODING_BLS_G2 *) + + let cost_ENCODING_BLS_G2 = S.safe_int 30 + + (* model B58CHECK_ENCODING_CHAIN_ID *) + let cost_B58CHECK_ENCODING_CHAIN_ID = S.safe_int 1_600 + + (* model B58CHECK_ENCODING_PUBLIC_KEY_HASH_ed25519 *) + let cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_ed25519 = S.safe_int 3_300 + + (* model B58CHECK_ENCODING_PUBLIC_KEY_HASH_p256 *) + let cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_p256 = S.safe_int 3_750 + + (* model B58CHECK_ENCODING_PUBLIC_KEY_HASH_secp256k1 *) + let cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_secp256k1 = S.safe_int 3_300 + + (* model B58CHECK_ENCODING_PUBLIC_KEY_ed25519 *) + let cost_B58CHECK_ENCODING_PUBLIC_KEY_ed25519 = S.safe_int 4_500 + + (* model B58CHECK_ENCODING_PUBLIC_KEY_p256 *) + let cost_B58CHECK_ENCODING_PUBLIC_KEY_p256 = S.safe_int 5_300 + + (* model B58CHECK_ENCODING_PUBLIC_KEY_secp256k1 *) + let cost_B58CHECK_ENCODING_PUBLIC_KEY_secp256k1 = S.safe_int 5_000 + + (* model B58CHECK_ENCODING_SIGNATURE_ed25519 *) + let cost_B58CHECK_ENCODING_SIGNATURE_ed25519 = S.safe_int 8_700 + + (* model B58CHECK_ENCODING_SIGNATURE_p256 *) + let cost_B58CHECK_ENCODING_SIGNATURE_p256 = S.safe_int 8_700 + + (* model B58CHECK_ENCODING_SIGNATURE_secp256k1 *) + let cost_B58CHECK_ENCODING_SIGNATURE_secp256k1 = S.safe_int 8_700 + + (* model DECODING_CHAIN_ID *) + let cost_DECODING_CHAIN_ID = S.safe_int 50 + + (* model DECODING_PUBLIC_KEY_HASH_ed25519 *) + let cost_DECODING_PUBLIC_KEY_HASH_ed25519 = S.safe_int 50 + + (* model DECODING_PUBLIC_KEY_HASH_p256 *) + let cost_DECODING_PUBLIC_KEY_HASH_p256 = S.safe_int 60 + + (* model DECODING_PUBLIC_KEY_HASH_secp256k1 *) + let cost_DECODING_PUBLIC_KEY_HASH_secp256k1 = S.safe_int 60 + + (* model DECODING_PUBLIC_KEY_ed25519 *) + let cost_DECODING_PUBLIC_KEY_ed25519 = S.safe_int 60 + + (* model DECODING_PUBLIC_KEY_p256 *) + let cost_DECODING_PUBLIC_KEY_p256 = S.safe_int 25_000 + + (* model DECODING_PUBLIC_KEY_secp256k1 *) + let cost_DECODING_PUBLIC_KEY_secp256k1 = S.safe_int 5_300 + + (* model DECODING_SIGNATURE_ed25519 *) + let cost_DECODING_SIGNATURE_ed25519 = S.safe_int 30 + + (* model DECODING_SIGNATURE_p256 *) + let cost_DECODING_SIGNATURE_p256 = S.safe_int 30 + + (* model DECODING_SIGNATURE_secp256k1 *) + let cost_DECODING_SIGNATURE_secp256k1 = S.safe_int 30 + + (* model ENCODING_CHAIN_ID *) + let cost_ENCODING_CHAIN_ID = S.safe_int 50 + + (* model ENCODING_PUBLIC_KEY_HASH_ed25519 *) + let cost_ENCODING_PUBLIC_KEY_HASH_ed25519 = S.safe_int 70 + + (* model ENCODING_PUBLIC_KEY_HASH_p256 *) + let cost_ENCODING_PUBLIC_KEY_HASH_p256 = S.safe_int 80 + + (* model ENCODING_PUBLIC_KEY_HASH_secp256k1 *) + let cost_ENCODING_PUBLIC_KEY_HASH_secp256k1 = S.safe_int 70 + + (* model ENCODING_PUBLIC_KEY_ed25519 *) + let cost_ENCODING_PUBLIC_KEY_ed25519 = S.safe_int 80 + + (* model ENCODING_PUBLIC_KEY_p256 *) + let cost_ENCODING_PUBLIC_KEY_p256 = S.safe_int 450 + + (* model ENCODING_PUBLIC_KEY_secp256k1 *) + let cost_ENCODING_PUBLIC_KEY_secp256k1 = S.safe_int 490 + + (* model ENCODING_SIGNATURE_ed25519 *) + let cost_ENCODING_SIGNATURE_ed25519 = S.safe_int 40 + + (* model ENCODING_SIGNATURE_p256 *) + let cost_ENCODING_SIGNATURE_p256 = S.safe_int 40 + + (* model ENCODING_SIGNATURE_secp256k1 *) + let cost_ENCODING_SIGNATURE_secp256k1 = S.safe_int 40 + + (* model TIMESTAMP_READABLE_DECODING *) + let cost_TIMESTAMP_READABLE_DECODING = S.safe_int 130 + + (* model TIMESTAMP_READABLE_ENCODING *) + let cost_TIMESTAMP_READABLE_ENCODING = S.safe_int 900 + + (* model CHECK_PRINTABLE *) + let cost_CHECK_PRINTABLE size = + let open S_syntax in + S.safe_int 14 + (S.safe_int 10 * S.safe_int size) + + (* model MERGE_TYPES + This is the estimated cost of one iteration of merge_types, extracted + and copied manually from the parameter fit for the MERGE_TYPES benchmark + (the model is parametric on the size of the type, which we don't have + access to in O(1)). *) + let cost_MERGE_TYPES = S.safe_int 130 + + (* model TYPECHECKING_CODE + This is the cost of one iteration of parse_instr, extracted by hand from the + parameter fit for the TYPECHECKING_CODE benchmark. *) + let cost_TYPECHECKING_CODE = S.safe_int 375 + + (* model UNPARSING_CODE + This is the cost of one iteration of unparse_instr, extracted by hand from the + parameter fit for the UNPARSING_CODE benchmark. *) + let cost_UNPARSING_CODE = S.safe_int 200 + + (* model TYPECHECKING_DATA + This is the cost of one iteration of parse_data, extracted by hand from the + parameter fit for the TYPECHECKING_DATA benchmark. *) + let cost_TYPECHECKING_DATA = S.safe_int 240 + + (* model UNPARSING_DATA + This is the cost of one iteration of unparse_data, extracted by hand from the + parameter fit for the UNPARSING_DATA benchmark. *) + let cost_UNPARSING_DATA = S.safe_int 140 + + (* model PARSE_TYPE + This is the cost of one iteration of parse_ty, extracted by hand from the + parameter fit for the PARSE_TYPE benchmark. *) + let cost_PARSE_TYPE = S.safe_int 170 + + (* model UNPARSE_TYPE + This is the cost of one iteration of unparse_ty, extracted by hand from the + parameter fit for the UNPARSE_TYPE benchmark. *) + let cost_UNPARSE_TYPE = S.safe_int 185 + + (* TODO: benchmark *) + let cost_COMPARABLE_TY_OF_TY = S.safe_int 120 + + (* model SAPLING_TRANSACTION_ENCODING *) + let cost_SAPLING_TRANSACTION_ENCODING ~inputs ~outputs = + S.safe_int (1500 + (inputs * 160) + (outputs * 320)) + + (* model SAPLING_DIFF_ENCODING *) + let cost_SAPLING_DIFF_ENCODING ~nfs ~cms = + S.safe_int ((nfs * 22) + (cms * 215)) + end + + module Interpreter = struct + open Generated_costs_007 + + let drop = atomic_step_cost cost_N_Drop + + let dup = atomic_step_cost cost_N_Dup + + let swap = atomic_step_cost cost_N_Swap + + let push = atomic_step_cost cost_N_Const + + let cons_some = atomic_step_cost cost_N_Cons_some + + let cons_none = atomic_step_cost cost_N_Cons_none + + let if_none = atomic_step_cost cost_N_If_none + + let cons_pair = atomic_step_cost cost_N_Cons_pair + + let unpair = atomic_step_cost cost_N_Unpair + + let car = atomic_step_cost cost_N_Car + + let cdr = atomic_step_cost cost_N_Cdr + + let cons_left = atomic_step_cost cost_N_Left + + let cons_right = atomic_step_cost cost_N_Right + + let if_left = atomic_step_cost cost_N_If_left + + let cons_list = atomic_step_cost cost_N_Cons_list + + let nil = atomic_step_cost cost_N_Nil + + let if_cons = atomic_step_cost cost_N_If_cons + + let list_map : 'a Script_typed_ir.boxed_list -> Gas.cost = + fun {length; _} -> atomic_step_cost (cost_N_List_map length) + + let list_size = atomic_step_cost cost_N_List_size + + let list_iter : 'a Script_typed_ir.boxed_list -> Gas.cost = + fun {length; _} -> atomic_step_cost (cost_N_List_iter length) + + let empty_set = atomic_step_cost cost_N_Empty_set + + let set_iter (type a) ((module Box) : a Script_typed_ir.set) = + atomic_step_cost (cost_N_Set_iter Box.size) + + let set_mem (type a) (elt : a) ((module Box) : a Script_typed_ir.set) = + let elt_size = size_of_comparable Box.elt_ty elt in + atomic_step_cost (cost_N_Set_mem elt_size Box.size) + + let set_update (type a) (elt : a) ((module Box) : a Script_typed_ir.set) = + let elt_size = size_of_comparable Box.elt_ty elt in + atomic_step_cost (cost_N_Set_update elt_size Box.size) + + let set_size = atomic_step_cost cost_N_Set_size + + let empty_map = atomic_step_cost cost_N_Empty_map + + let map_map (type k v) ((module Box) : (k, v) Script_typed_ir.map) = + atomic_step_cost (cost_N_Map_map (snd Box.boxed)) + + let map_iter (type k v) ((module Box) : (k, v) Script_typed_ir.map) = + atomic_step_cost (cost_N_Map_iter (snd Box.boxed)) + + let map_mem (type k v) (elt : k) + ((module Box) : (k, v) Script_typed_ir.map) = + let elt_size = size_of_comparable Box.key_ty elt in + atomic_step_cost (cost_N_Map_mem elt_size (S.safe_int (snd Box.boxed))) + + let map_get (type k v) (elt : k) + ((module Box) : (k, v) Script_typed_ir.map) = + let elt_size = size_of_comparable Box.key_ty elt in + atomic_step_cost (cost_N_Map_get elt_size (S.safe_int (snd Box.boxed))) + + let map_update (type k v) (elt : k) + ((module Box) : (k, v) Script_typed_ir.map) = + let elt_size = size_of_comparable Box.key_ty elt in + atomic_step_cost + (cost_N_Map_update elt_size (S.safe_int (snd Box.boxed))) + + let map_get_and_update (type k v) (elt : k) + (m : (k, v) Script_typed_ir.map) = + map_get elt m +@ map_update elt m + + let map_size = atomic_step_cost cost_N_Map_size + + let big_map_elt_size = S.safe_int Script_expr_hash.size + + let big_map_mem ({size; _} : _ Script_typed_ir.big_map_overlay) = + atomic_step_cost (cost_N_Map_mem big_map_elt_size (S.safe_int size)) + + let big_map_get ({size; _} : _ Script_typed_ir.big_map_overlay) = + atomic_step_cost (cost_N_Map_get big_map_elt_size (S.safe_int size)) + + let big_map_update ({size; _} : _ Script_typed_ir.big_map_overlay) = + atomic_step_cost (cost_N_Map_update big_map_elt_size (S.safe_int size)) + + let big_map_get_and_update m = big_map_get m +@ big_map_update m + + let add_seconds_timestamp : + 'a Script_int.num -> Script_timestamp.t -> Gas.cost = + fun seconds timestamp -> + let seconds_bytes = int_bytes seconds in + let timestamp_bytes = z_bytes (Script_timestamp.to_zint timestamp) in + atomic_step_cost (cost_N_Add_intint seconds_bytes timestamp_bytes) + + let sub_seconds_timestamp : + 'a Script_int.num -> Script_timestamp.t -> Gas.cost = + fun seconds timestamp -> + let seconds_bytes = int_bytes seconds in + let timestamp_bytes = z_bytes (Script_timestamp.to_zint timestamp) in + atomic_step_cost (cost_N_Sub_int seconds_bytes timestamp_bytes) + + let diff_timestamps t1 t2 = + let t1_bytes = z_bytes (Script_timestamp.to_zint t1) in + let t2_bytes = z_bytes (Script_timestamp.to_zint t2) in + atomic_step_cost (cost_N_Sub_int t1_bytes t2_bytes) + + let concat_string_pair s1 s2 = + atomic_step_cost + (cost_N_Concat_string_pair (String.length s1) (String.length s2)) + + let slice_string s = + atomic_step_cost (cost_N_Slice_string (String.length s)) + + let string_size = atomic_step_cost cost_N_String_size + + let concat_bytes_pair b1 b2 = + atomic_step_cost + (cost_N_Concat_string_pair (Bytes.length b1) (Bytes.length b2)) + + let slice_bytes b = atomic_step_cost (cost_N_Slice_string (Bytes.length b)) + + let bytes_size = atomic_step_cost cost_N_String_size + + let add_tez = atomic_step_cost cost_N_Add_tez + + let sub_tez = atomic_step_cost cost_N_Sub_tez + + let mul_teznat n = atomic_step_cost (cost_N_Mul_teznat (int_bytes n)) + + let bool_or = atomic_step_cost cost_N_Or + + let bool_and = atomic_step_cost cost_N_And + + let bool_xor = atomic_step_cost cost_N_Xor + + let bool_not = atomic_step_cost cost_N_Not + + let is_nat = atomic_step_cost cost_N_Is_nat + + let abs_int i = atomic_step_cost (cost_N_Abs_int (int_bytes i)) + + let int_nat = atomic_step_cost cost_N_Int_nat + + let neg_int i = atomic_step_cost (cost_N_Neg_int (int_bytes i)) + + let neg_nat n = atomic_step_cost (cost_N_Neg_int (int_bytes n)) + + let add_bigint i1 i2 = + atomic_step_cost (cost_N_Add_intint (int_bytes i1) (int_bytes i2)) + + let sub_bigint i1 i2 = + atomic_step_cost (cost_N_Sub_int (int_bytes i1) (int_bytes i2)) + + let mul_bigint i1 i2 = + atomic_step_cost (cost_N_Mul_intint (int_bytes i1) (int_bytes i2)) + + let ediv_teznat _tez _n = atomic_step_cost cost_N_Ediv_teznat + + let ediv_tez = atomic_step_cost cost_N_Ediv_tez + + let ediv_bigint i1 i2 = + atomic_step_cost (cost_N_Ediv_natnat (int_bytes i1) (int_bytes i2)) + + let eq = atomic_step_cost cost_N_Eq + + let lsl_nat shifted = atomic_step_cost (cost_N_Lsl_nat (int_bytes shifted)) + + let lsr_nat shifted = atomic_step_cost (cost_N_Lsr_nat (int_bytes shifted)) + + let or_nat n1 n2 = + atomic_step_cost (cost_N_Or_nat (int_bytes n1) (int_bytes n2)) + + let and_nat n1 n2 = + atomic_step_cost (cost_N_And_nat (int_bytes n1) (int_bytes n2)) + + let xor_nat n1 n2 = + atomic_step_cost (cost_N_Xor_nat (int_bytes n1) (int_bytes n2)) + + let not_int i = atomic_step_cost (cost_N_Not_int (int_bytes i)) + + let not_nat = not_int + + let seq = atomic_step_cost cost_N_Seq + + let if_ = atomic_step_cost cost_N_If + + let loop = atomic_step_cost cost_N_Loop + + let loop_left = atomic_step_cost cost_N_Loop_left + + let dip = atomic_step_cost cost_N_Dip + + let check_signature (pkey : Signature.public_key) b = + let cost = + match pkey with + | Ed25519 _ -> + cost_N_Check_signature_ed25519 (Bytes.length b) + | Secp256k1 _ -> + cost_N_Check_signature_secp256k1 (Bytes.length b) + | P256 _ -> + cost_N_Check_signature_p256 (Bytes.length b) + in + atomic_step_cost cost + + let blake2b b = atomic_step_cost (cost_N_Blake2b (Bytes.length b)) + + let sha256 b = atomic_step_cost (cost_N_Sha256 (Bytes.length b)) + + let sha512 b = atomic_step_cost (cost_N_Sha512 (Bytes.length b)) + + let dign n = atomic_step_cost (cost_N_Dig n) + + let dugn n = atomic_step_cost (cost_N_Dug n) + + let dipn n = atomic_step_cost (cost_N_DipN n) + + let dropn n = atomic_step_cost (cost_N_DropN n) + + let voting_power = atomic_step_cost cost_N_Voting_power + + let total_voting_power = atomic_step_cost cost_N_Total_voting_power + + let keccak b = atomic_step_cost (cost_N_Keccak (Bytes.length b)) + + let sha3 b = atomic_step_cost (cost_N_Sha3 (Bytes.length b)) + + let add_bls12_381_g1 = atomic_step_cost cost_N_Add_bls12_381_g1 + + let add_bls12_381_g2 = atomic_step_cost cost_N_Add_bls12_381_g2 + + let add_bls12_381_fr = atomic_step_cost cost_N_Add_bls12_381_fr + + let mul_bls12_381_g1 = atomic_step_cost cost_N_Mul_bls12_381_g1 + + let mul_bls12_381_g2 = atomic_step_cost cost_N_Mul_bls12_381_g2 + + let mul_bls12_381_fr = atomic_step_cost cost_N_Mul_bls12_381_fr + + let mul_bls12_381_fr_z = atomic_step_cost cost_N_Mul_bls12_381_fr_z + + let int_bls12_381_fr = atomic_step_cost cost_N_Int_bls12_381_fr + + let neg_bls12_381_g1 = atomic_step_cost cost_N_Neg_bls12_381_g1 + + let neg_bls12_381_g2 = atomic_step_cost cost_N_Neg_bls12_381_g2 + + let neg_bls12_381_fr = atomic_step_cost cost_N_Neg_bls12_381_fr + + let neq = atomic_step_cost cost_N_Neq + + let nop = atomic_step_cost cost_N_Nop + + let pairing_check_bls12_381 (l : 'a Script_typed_ir.boxed_list) = + atomic_step_cost (cost_N_Pairing_check_bls12_381 l.length) + + let comb n = atomic_step_cost (cost_N_Comb n) + + let uncomb n = atomic_step_cost (cost_N_Uncomb n) + + let comb_get n = atomic_step_cost (cost_N_Comb_get n) + + let comb_set n = atomic_step_cost (cost_N_Comb_set n) + + let dupn n = atomic_step_cost (cost_N_DupN n) + + let sapling_verify_update ~inputs ~outputs = + let open S_syntax in + atomic_step_cost + ( S.safe_int 85_000 + + (S.safe_int inputs * S.safe_int 4) + + (S.safe_int outputs * S.safe_int 30) ) + + (* --------------------------------------------------------------------- *) + (* Semi-hand-crafted models *) + let compare_unit = atomic_step_cost (S.safe_int 10) + + let compare_union_tag = atomic_step_cost (S.safe_int 10) + + let compare_option_tag = atomic_step_cost (S.safe_int 10) + + let compare_bool = atomic_step_cost (cost_N_Compare_bool 1 1) + + let compare_signature = atomic_step_cost (S.safe_int 92) + + let compare_string s1 s2 = + atomic_step_cost + (cost_N_Compare_string (String.length s1) (String.length s2)) + + let compare_bytes b1 b2 = + atomic_step_cost + (cost_N_Compare_string (Bytes.length b1) (Bytes.length b2)) + + let compare_mutez = atomic_step_cost (cost_N_Compare_mutez 8 8) + + let compare_int i1 i2 = + atomic_step_cost (cost_N_Compare_int (int_bytes i1) (int_bytes i2)) + + let compare_nat n1 n2 = + atomic_step_cost (cost_N_Compare_int (int_bytes n1) (int_bytes n2)) + + let compare_key_hash = + let sz = Signature.Public_key_hash.size in + atomic_step_cost (cost_N_Compare_key_hash sz sz) + + let compare_key = atomic_step_cost (S.safe_int 92) + + let compare_timestamp t1 t2 = + atomic_step_cost + (cost_N_Compare_timestamp + (z_bytes (Script_timestamp.to_zint t1)) + (z_bytes (Script_timestamp.to_zint t2))) + + let compare_address = + let sz = Signature.Public_key_hash.size + Chain_id.size in + atomic_step_cost (cost_N_Compare_address sz sz) + + let compare_chain_id = atomic_step_cost (S.safe_int 30) + + let rec compare : type a. a Script_typed_ir.comparable_ty -> a -> a -> cost + = + fun ty x y -> + match ty with + | Unit_key _ -> + compare_unit + | Never_key _ -> ( + match x with _ -> . ) + | Bool_key _ -> + compare_bool + | String_key _ -> + compare_string x y + | Signature_key _ -> + compare_signature + | Bytes_key _ -> + compare_bytes x y + | Mutez_key _ -> + compare_mutez + | Int_key _ -> + compare_int x y + | Nat_key _ -> + compare_nat x y + | Key_hash_key _ -> + compare_key_hash + | Key_key _ -> + compare_key + | Timestamp_key _ -> + compare_timestamp x y + | Address_key _ -> + compare_address + | Chain_id_key _ -> + compare_chain_id + | Pair_key ((tl, _), (tr, _), _) -> + (* Reasonable over-approximation of the cost of lexicographic comparison. *) + let (xl, xr) = x in + let (yl, yr) = y in + compare tl xl yl +@ compare tr xr yr + | Union_key ((tl, _), (tr, _), _) -> ( + compare_union_tag + +@ + match (x, y) with + | (L x, L y) -> + compare tl x y + | (L _, R _) -> + free + | (R _, L _) -> + free + | (R x, R y) -> + compare tr x y ) + | Option_key (t, _) -> ( + compare_option_tag + +@ + match (x, y) with + | (None, None) -> + free + | (None, Some _) -> + free + | (Some _, None) -> + free + | (Some x, Some y) -> + compare t x y ) + + (* --------------------------------------------------------------------- *) + (* Hand-crafted models *) + + (* The cost functions below where not benchmarked, a cost model was derived + from looking at similar instructions. *) + + let sapling_empty_state = empty_map + + (* Cost for Concat_string is paid in two steps: when entering the interpreter, + the user pays for the cost of computing the information necessary to compute + the actual gas (so it's meta-gas): indeed, one needs to run through the + list of strings to compute the total allocated cost. + [concat_string_precheck] corresponds to the meta-gas cost of this computation. + *) + let concat_string_precheck (l : 'a Script_typed_ir.boxed_list) = + (* we set the precheck to be slightly more expensive than cost_N_List_iter *) + atomic_step_cost (S.mul (S.safe_int l.length) (S.safe_int 10)) + + (* This is the cost of allocating a string and blitting existing ones into it. *) + let concat_string total_bytes = + atomic_step_cost + S.(add (S.safe_int 100) (S.ediv total_bytes (S.safe_int 10))) + + (* Same story as Concat_string. *) + let concat_bytes total_bytes = + atomic_step_cost + S.(add (S.safe_int 100) (S.ediv total_bytes (S.safe_int 10))) + + (* Cost of additional call to logger + overhead of setting up call to [interp]. *) + let exec = atomic_step_cost (S.safe_int 100) + + (* Heavy computation happens in the [unparse_data], [unparse_ty] + functions which are carbonated. We must account for allocating + the Micheline lambda wrapper. *) + let apply = atomic_step_cost (S.safe_int 1000) + + (* Pushing a pointer on the stack. *) + let lambda = push + + (* Pusing an address on the stack. *) + let address = push + + (* Most computation happens in [parse_contract_from_script], which is carbonated. + Account for pushing on the stack. *) + let contract = push + + (* Most computation happens in [collect_lazy_storage], [extract_lazy_storage_diff] + and [unparse_data] which are carbonated. The instruction-specific overhead + is mostly that of updating the internal nonce, which we approximate by the + cost of a push. *) + let transfer_tokens = Gas.(push +@ push) + + (* Wrapping a value and pushing it on the stack. *) + let implicit_account = push + + (* As for [transfer_token], most computation happens elsewhere. + We still account for the overhead of updating the internal_nonce. *) + let create_contract = Gas.(push +@ push) + + (* Increments the internal_nonce counter. *) + let set_delegate = Gas.(push +@ push) + + (* Cost of access taken care of in Contract_storage.get_balance_carbonated *) + let balance = Gas.free + + (* Accessing the raw_context, Small arithmetic & pushing on the stack. *) + let level = atomic_step_cost (S.mul (S.safe_int 2) cost_N_Const) + + (* Same as [cost_level] *) + let now = level + + (* Public keys are hashed with Blake2b *) + let hash_key _pk = atomic_step_cost (cost_N_Blake2b public_key_size) + + (* Pushes on the stack an element from the [step_constants] record. *) + let source = push + + (* Same as cost_source *) + let sender = source + + (* Same as cost_source *) + let self = source + + (* Same as cost_source *) + let self_address = source + + (* Same as cost_source *) + let amount = source + + (* Same as cost_source *) + let chain_id = source + + (* TODO benchmark *) + (* FIXME: imported from 006, needs proper benchmarks *) + let unpack_failed bytes = + (* We cannot instrument failed deserialization, + so we take worst case fees: a set of size 1 bytes values. *) + let blen = Bytes.length bytes in + let len = S.safe_int blen in + let d = Z.numbits (Z.of_int blen) in + (len *@ alloc_mbytes_cost 1) + +@ len + *@ ( S.safe_int d + *@ (alloc_cost (S.safe_int 3) +@ step_cost (S.safe_int 1)) ) + + let ticket = atomic_step_cost (S.safe_int 80) + + let read_ticket = atomic_step_cost (S.safe_int 80) + + let split_ticket ticket_amount amount_a amount_b = + ticket + +@ add_bigint amount_a amount_b + +@ compare_nat ticket_amount ticket_amount + + let join_tickets : + 'a Script_typed_ir.comparable_ty -> + 'a Script_typed_ir.ticket -> + 'a Script_typed_ir.ticket -> + Gas.cost = + fun ty ticket_a ticket_b -> + ticket +@ compare_address + +@ add_bigint ticket_a.amount ticket_b.amount + +@ compare ty ticket_a.contents ticket_b.contents + end + + module Typechecking = struct + open Generated_costs_007 + + let public_key_optimized = + atomic_step_cost + @@ S.( + max + cost_DECODING_PUBLIC_KEY_ed25519 + (max + cost_DECODING_PUBLIC_KEY_secp256k1 + cost_DECODING_PUBLIC_KEY_p256)) + + let public_key_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_DECODING_PUBLIC_KEY_ed25519 + (max + cost_B58CHECK_DECODING_PUBLIC_KEY_secp256k1 + cost_B58CHECK_DECODING_PUBLIC_KEY_p256)) + + let key_hash_optimized = + atomic_step_cost + @@ S.( + max + cost_DECODING_PUBLIC_KEY_HASH_ed25519 + (max + cost_DECODING_PUBLIC_KEY_HASH_secp256k1 + cost_DECODING_PUBLIC_KEY_HASH_p256)) + + let key_hash_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_ed25519 + (max + cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_secp256k1 + cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_p256)) + + let signature_optimized = + atomic_step_cost + @@ S.( + max + cost_DECODING_SIGNATURE_ed25519 + (max + cost_DECODING_SIGNATURE_secp256k1 + cost_DECODING_SIGNATURE_p256)) + + let signature_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_DECODING_SIGNATURE_ed25519 + (max + cost_B58CHECK_DECODING_SIGNATURE_secp256k1 + cost_B58CHECK_DECODING_SIGNATURE_p256)) + + let chain_id_optimized = atomic_step_cost cost_DECODING_CHAIN_ID + + let chain_id_readable = atomic_step_cost cost_B58CHECK_DECODING_CHAIN_ID + + (* Reasonable approximation *) + let address_optimized = key_hash_optimized + + (* Reasonable approximation *) + let contract_optimized = key_hash_optimized + + (* Reasonable approximation *) + let contract_readable = key_hash_readable + + let bls12_381_g1 = atomic_step_cost cost_DECODING_BLS_G1 + + let bls12_381_g2 = atomic_step_cost cost_DECODING_BLS_G2 + + let bls12_381_fr = atomic_step_cost cost_DECODING_BLS_FR + + let check_printable s = + atomic_step_cost (cost_CHECK_PRINTABLE (String.length s)) + + let merge_cycle = atomic_step_cost cost_MERGE_TYPES + + let parse_type_cycle = atomic_step_cost cost_PARSE_TYPE + + let parse_instr_cycle = atomic_step_cost cost_TYPECHECKING_CODE + + let parse_data_cycle = atomic_step_cost cost_TYPECHECKING_DATA + + let comparable_ty_of_ty_cycle = atomic_step_cost cost_COMPARABLE_TY_OF_TY + + (* Cost of a cycle of checking that a type is dupable *) + (* TODO: bench *) + let check_dupable_cycle = atomic_step_cost cost_TYPECHECKING_DATA + + let bool = free + + let unit = free + + let timestamp_readable = atomic_step_cost cost_TIMESTAMP_READABLE_DECODING + + (* Reasonable estimate. *) + let contract = Gas.(S.safe_int 2 *@ public_key_readable) + + (* Assuming unflattened storage: /contracts/hash1/.../hash6/key/balance, + balance stored on 64 bits *) + let contract_exists = + Gas.cost_of_repr + @@ Storage_costs.read_access ~path_length:9 ~read_bytes:8 + + (* Constructing proof arguments consists in a decreasing loop in the result + monad, allocating at each step. We charge a reasonable overapproximation. *) + let proof_argument n = + atomic_step_cost (S.mul (S.safe_int n) (S.safe_int 50)) + end + + module Unparsing = struct + open Generated_costs_007 + + let public_key_optimized = + atomic_step_cost + @@ S.( + max + cost_ENCODING_PUBLIC_KEY_ed25519 + (max + cost_ENCODING_PUBLIC_KEY_secp256k1 + cost_ENCODING_PUBLIC_KEY_p256)) + + let public_key_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_ENCODING_PUBLIC_KEY_ed25519 + (max + cost_B58CHECK_ENCODING_PUBLIC_KEY_secp256k1 + cost_B58CHECK_ENCODING_PUBLIC_KEY_p256)) + + let key_hash_optimized = + atomic_step_cost + @@ S.( + max + cost_ENCODING_PUBLIC_KEY_HASH_ed25519 + (max + cost_ENCODING_PUBLIC_KEY_HASH_secp256k1 + cost_ENCODING_PUBLIC_KEY_HASH_p256)) + + let key_hash_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_ed25519 + (max + cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_secp256k1 + cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_p256)) + + let signature_optimized = + atomic_step_cost + @@ S.( + max + cost_ENCODING_SIGNATURE_ed25519 + (max + cost_ENCODING_SIGNATURE_secp256k1 + cost_ENCODING_SIGNATURE_p256)) + + let signature_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_ENCODING_SIGNATURE_ed25519 + (max + cost_B58CHECK_ENCODING_SIGNATURE_secp256k1 + cost_B58CHECK_ENCODING_SIGNATURE_p256)) + + let chain_id_optimized = atomic_step_cost cost_ENCODING_CHAIN_ID + + let chain_id_readable = atomic_step_cost cost_B58CHECK_ENCODING_CHAIN_ID + + let timestamp_readable = atomic_step_cost cost_TIMESTAMP_READABLE_ENCODING + + (* Reasonable approximation *) + let address_optimized = key_hash_optimized + + (* Reasonable approximation *) + let contract_optimized = key_hash_optimized + + (* Reasonable approximation *) + let contract_readable = key_hash_readable + + let bls12_381_g1 = atomic_step_cost cost_ENCODING_BLS_G1 + + let bls12_381_g2 = atomic_step_cost cost_ENCODING_BLS_G2 + + let bls12_381_fr = atomic_step_cost cost_ENCODING_BLS_FR + + let unparse_type_cycle = atomic_step_cost cost_UNPARSE_TYPE + + let unparse_instr_cycle = atomic_step_cost cost_UNPARSING_CODE + + let unparse_data_cycle = atomic_step_cost cost_UNPARSING_DATA + + let unit = Gas.free + + (* Reasonable estimate. *) + let contract = Gas.(S.safe_int 2 *@ public_key_readable) + + (* Reuse 006 costs. *) + let operation bytes = Script.bytes_node_cost bytes + + let sapling_transaction (t : Sapling.transaction) = + let inputs = List.length t.inputs in + let outputs = List.length t.outputs in + atomic_step_cost (cost_SAPLING_TRANSACTION_ENCODING ~inputs ~outputs) + + let sapling_diff (d : Sapling.diff) = + let nfs = List.length d.nullifiers in + let cms = List.length d.commitments_and_ciphertexts in + atomic_step_cost (cost_SAPLING_DIFF_ENCODING ~nfs ~cms) + end +end diff --git a/src/proto_009_PsFLoren/lib_protocol/michelson_v1_gas.mli b/src/proto_009_PsFLoren/lib_protocol/michelson_v1_gas.mli new file mode 100644 index 0000000000000000000000000000000000000000..788e52e0cb56cb7713ed75784cbc331bc3a957ae --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/michelson_v1_gas.mli @@ -0,0 +1,422 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +module Cost_of : sig + val manager_operation : Gas.cost + + module Interpreter : sig + val drop : Gas.cost + + val dup : Gas.cost + + val swap : Gas.cost + + val push : Gas.cost + + val cons_some : Gas.cost + + val cons_none : Gas.cost + + val if_none : Gas.cost + + val cons_pair : Gas.cost + + val unpair : Gas.cost + + val car : Gas.cost + + val cdr : Gas.cost + + val cons_left : Gas.cost + + val cons_right : Gas.cost + + val if_left : Gas.cost + + val cons_list : Gas.cost + + val nil : Gas.cost + + val if_cons : Gas.cost + + val list_map : 'a Script_typed_ir.boxed_list -> Gas.cost + + val list_size : Gas.cost + + val list_iter : 'a Script_typed_ir.boxed_list -> Gas.cost + + val empty_set : Gas.cost + + val set_iter : 'a Script_typed_ir.set -> Gas.cost + + val set_mem : 'a -> 'a Script_typed_ir.set -> Gas.cost + + val set_update : 'a -> 'a Script_typed_ir.set -> Gas.cost + + val set_size : Gas.cost + + val empty_map : Gas.cost + + val map_map : ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_iter : ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_mem : 'k -> ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_get : 'k -> ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_update : 'k -> ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_get_and_update : 'k -> ('k, 'v) Script_typed_ir.map -> Gas.cost + + val big_map_mem : (_, _) Script_typed_ir.big_map_overlay -> Gas.cost + + val big_map_get : (_, _) Script_typed_ir.big_map_overlay -> Gas.cost + + val big_map_update : (_, _) Script_typed_ir.big_map_overlay -> Gas.cost + + val big_map_get_and_update : + (_, _) Script_typed_ir.big_map_overlay -> Gas.cost + + val map_size : Gas.cost + + val add_seconds_timestamp : + 'a Script_int.num -> Script_timestamp.t -> Gas.cost + + val sub_seconds_timestamp : + 'a Script_int.num -> Script_timestamp.t -> Gas.cost + + val diff_timestamps : Script_timestamp.t -> Script_timestamp.t -> Gas.cost + + val concat_string_pair : string -> string -> Gas.cost + + val slice_string : string -> Gas.cost + + val string_size : Gas.cost + + val concat_bytes_pair : bytes -> bytes -> Gas.cost + + val slice_bytes : bytes -> Gas.cost + + val bytes_size : Gas.cost + + val add_tez : Gas.cost + + val sub_tez : Gas.cost + + val mul_teznat : 'a Script_int.num -> Gas.cost + + val bool_or : Gas.cost + + val bool_and : Gas.cost + + val bool_xor : Gas.cost + + val bool_not : Gas.cost + + val is_nat : Gas.cost + + val abs_int : 'a Script_int.num -> Gas.cost + + val int_nat : Gas.cost + + val neg_int : 'a Script_int.num -> Gas.cost + + val neg_nat : 'a Script_int.num -> Gas.cost + + val add_bigint : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val sub_bigint : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val mul_bigint : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val ediv_teznat : 'a -> 'b Script_int.num -> Gas.cost + + val ediv_tez : Gas.cost + + val ediv_bigint : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val eq : Gas.cost + + val lsl_nat : 'a Script_int.num -> Gas.cost + + val lsr_nat : 'a Script_int.num -> Gas.cost + + val or_nat : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val and_nat : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val xor_nat : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val not_int : 'a Script_int.num -> Gas.cost + + val not_nat : 'a Script_int.num -> Gas.cost + + val seq : Gas.cost + + val if_ : Gas.cost + + val loop : Gas.cost + + val loop_left : Gas.cost + + val dip : Gas.cost + + val check_signature : Signature.public_key -> bytes -> Gas.cost + + val blake2b : bytes -> Gas.cost + + val sha256 : bytes -> Gas.cost + + val sha512 : bytes -> Gas.cost + + val dign : int -> Gas.cost + + val dugn : int -> Gas.cost + + val dipn : int -> Gas.cost + + val dropn : int -> Gas.cost + + val voting_power : Gas.cost + + val total_voting_power : Gas.cost + + val keccak : bytes -> Gas.cost + + val sha3 : bytes -> Gas.cost + + val add_bls12_381_g1 : Gas.cost + + val add_bls12_381_g2 : Gas.cost + + val add_bls12_381_fr : Gas.cost + + val mul_bls12_381_g1 : Gas.cost + + val mul_bls12_381_g2 : Gas.cost + + val mul_bls12_381_fr : Gas.cost + + val mul_bls12_381_fr_z : Gas.cost + + val int_bls12_381_fr : Gas.cost + + val neg_bls12_381_g1 : Gas.cost + + val neg_bls12_381_g2 : Gas.cost + + val neg_bls12_381_fr : Gas.cost + + val neq : Gas.cost + + val nop : Gas.cost + + val pairing_check_bls12_381 : 'a Script_typed_ir.boxed_list -> Gas.cost + + val comb : int -> Gas.cost + + val uncomb : int -> Gas.cost + + val comb_get : int -> Gas.cost + + val comb_set : int -> Gas.cost + + val dupn : int -> Gas.cost + + val compare : 'a Script_typed_ir.comparable_ty -> 'a -> 'a -> Gas.cost + + val concat_string_precheck : 'a Script_typed_ir.boxed_list -> Gas.cost + + val concat_string : + Saturation_repr.may_saturate Saturation_repr.t -> Gas.cost + + val concat_bytes : + Saturation_repr.may_saturate Saturation_repr.t -> Gas.cost + + val exec : Gas.cost + + val apply : Gas.cost + + val lambda : Gas.cost + + val address : Gas.cost + + val contract : Gas.cost + + val transfer_tokens : Gas.cost + + val implicit_account : Gas.cost + + val create_contract : Gas.cost + + val set_delegate : Gas.cost + + val balance : Gas.cost + + val level : Gas.cost + + val now : Gas.cost + + val hash_key : Signature.Public_key.t -> Gas.cost + + val source : Gas.cost + + val sender : Gas.cost + + val self : Gas.cost + + val self_address : Gas.cost + + val amount : Gas.cost + + val chain_id : Gas.cost + + val unpack_failed : bytes -> Gas.cost + + val sapling_empty_state : Gas.cost + + val sapling_verify_update : inputs:int -> outputs:int -> Gas.cost + + val ticket : Gas.cost + + val read_ticket : Gas.cost + + val split_ticket : + 'a Script_int.num -> 'a Script_int.num -> 'a Script_int.num -> Gas.cost + + val join_tickets : + 'a Script_typed_ir.comparable_ty -> + 'a Script_typed_ir.ticket -> + 'a Script_typed_ir.ticket -> + Gas.cost + end + + module Typechecking : sig + val public_key_optimized : Gas.cost + + val public_key_readable : Gas.cost + + val key_hash_optimized : Gas.cost + + val key_hash_readable : Gas.cost + + val signature_optimized : Gas.cost + + val signature_readable : Gas.cost + + val chain_id_optimized : Gas.cost + + val chain_id_readable : Gas.cost + + val address_optimized : Gas.cost + + val contract_optimized : Gas.cost + + val contract_readable : Gas.cost + + val bls12_381_g1 : Gas.cost + + val bls12_381_g2 : Gas.cost + + val bls12_381_fr : Gas.cost + + val check_printable : string -> Gas.cost + + val merge_cycle : Gas.cost + + val parse_type_cycle : Gas.cost + + val parse_instr_cycle : Gas.cost + + val parse_data_cycle : Gas.cost + + val comparable_ty_of_ty_cycle : Gas.cost + + val check_dupable_cycle : Gas.cost + + val bool : Gas.cost + + val unit : Gas.cost + + val timestamp_readable : Gas.cost + + val contract : Gas.cost + + val contract_exists : Gas.cost + + val proof_argument : int -> Gas.cost + end + + module Unparsing : sig + val public_key_optimized : Gas.cost + + val public_key_readable : Gas.cost + + val key_hash_optimized : Gas.cost + + val key_hash_readable : Gas.cost + + val signature_optimized : Gas.cost + + val signature_readable : Gas.cost + + val chain_id_optimized : Gas.cost + + val chain_id_readable : Gas.cost + + val timestamp_readable : Gas.cost + + val address_optimized : Gas.cost + + val contract_optimized : Gas.cost + + val contract_readable : Gas.cost + + val bls12_381_g1 : Gas.cost + + val bls12_381_g2 : Gas.cost + + val bls12_381_fr : Gas.cost + + val unparse_type_cycle : Gas.cost + + val unparse_instr_cycle : Gas.cost + + val unparse_data_cycle : Gas.cost + + val unit : Gas.cost + + val contract : Gas.cost + + val operation : bytes -> Gas.cost + + val sapling_transaction : Sapling.transaction -> Gas.cost + + val sapling_diff : Sapling.diff -> Gas.cost + end +end diff --git a/src/proto_009_PsFLoren/lib_protocol/michelson_v1_primitives.ml b/src/proto_009_PsFLoren/lib_protocol/michelson_v1_primitives.ml new file mode 100644 index 0000000000000000000000000000000000000000..005cd37f60ca81b74449f13fdc8c5b11243fab1d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/michelson_v1_primitives.ml @@ -0,0 +1,1166 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Micheline + +type error += Unknown_primitive_name of string + +type error += Invalid_case of string + +type error += + | Invalid_primitive_name of + string Micheline.canonical * Micheline.canonical_location + +type prim = + | K_parameter + | K_storage + | K_code + | D_False + | D_Elt + | D_Left + | D_None + | D_Pair + | D_Right + | D_Some + | D_True + | D_Unit + | I_PACK + | I_UNPACK + | I_BLAKE2B + | I_SHA256 + | I_SHA512 + | I_ABS + | I_ADD + | I_AMOUNT + | I_AND + | I_BALANCE + | I_CAR + | I_CDR + | I_CHAIN_ID + | I_CHECK_SIGNATURE + | I_COMPARE + | I_CONCAT + | I_CONS + | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT + | I_IMPLICIT_ACCOUNT + | I_DIP + | I_DROP + | I_DUP + | I_EDIV + | I_EMPTY_BIG_MAP + | I_EMPTY_MAP + | I_EMPTY_SET + | I_EQ + | I_EXEC + | I_APPLY + | I_FAILWITH + | I_GE + | I_GET + | I_GET_AND_UPDATE + | I_GT + | I_HASH_KEY + | I_IF + | I_IF_CONS + | I_IF_LEFT + | I_IF_NONE + | I_INT + | I_LAMBDA + | I_LE + | I_LEFT + | I_LEVEL + | I_LOOP + | I_LSL + | I_LSR + | I_LT + | I_MAP + | I_MEM + | I_MUL + | I_NEG + | I_NEQ + | I_NIL + | I_NONE + | I_NOT + | I_NOW + | I_OR + | I_PAIR + | I_UNPAIR + | I_PUSH + | I_RIGHT + | I_SIZE + | I_SOME + | I_SOURCE + | I_SENDER + | I_SELF + | I_SELF_ADDRESS + | I_SLICE + | I_STEPS_TO_QUOTA + | I_SUB + | I_SWAP + | I_TRANSFER_TOKENS + | I_SET_DELEGATE + | I_UNIT + | I_UPDATE + | I_XOR + | I_ITER + | I_LOOP_LEFT + | I_ADDRESS + | I_CONTRACT + | I_ISNAT + | I_CAST + | I_RENAME + | I_SAPLING_EMPTY_STATE + | I_SAPLING_VERIFY_UPDATE + | I_DIG + | I_DUG + | I_NEVER + | I_VOTING_POWER + | I_TOTAL_VOTING_POWER + | I_KECCAK + | I_SHA3 + | I_PAIRING_CHECK + | I_TICKET + | I_READ_TICKET + | I_SPLIT_TICKET + | I_JOIN_TICKETS + | T_bool + | T_contract + | T_int + | T_key + | T_key_hash + | T_lambda + | T_list + | T_map + | T_big_map + | T_nat + | T_option + | T_or + | T_pair + | T_set + | T_signature + | T_string + | T_bytes + | T_mutez + | T_timestamp + | T_unit + | T_operation + | T_address + | T_sapling_transaction + | T_sapling_state + | T_chain_id + | T_never + | T_bls12_381_g1 + | T_bls12_381_g2 + | T_bls12_381_fr + | T_ticket + +(* Auxiliary types for error documentation. + All the prim constructor prefixes must match their namespace. *) +type namespace = + | (* prefix "T" *) Type_namespace + | (* prefix "D" *) Constant_namespace + | (* prefix "I" *) Instr_namespace + | (* prefix "K" *) Keyword_namespace + +let namespace = function + | K_code | K_parameter | K_storage -> + Keyword_namespace + | D_Elt + | D_False + | D_Left + | D_None + | D_Pair + | D_Right + | D_Some + | D_True + | D_Unit -> + Constant_namespace + | I_ABS + | I_ADD + | I_ADDRESS + | I_AMOUNT + | I_AND + | I_APPLY + | I_BALANCE + | I_BLAKE2B + | I_CAR + | I_CAST + | I_CDR + | I_CHAIN_ID + | I_CHECK_SIGNATURE + | I_COMPARE + | I_CONCAT + | I_CONS + | I_CONTRACT + | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT + | I_DIG + | I_DIP + | I_DROP + | I_DUG + | I_DUP + | I_EDIV + | I_EMPTY_BIG_MAP + | I_EMPTY_MAP + | I_EMPTY_SET + | I_EQ + | I_EXEC + | I_FAILWITH + | I_GE + | I_GET + | I_GET_AND_UPDATE + | I_GT + | I_HASH_KEY + | I_IF + | I_IF_CONS + | I_IF_LEFT + | I_IF_NONE + | I_IMPLICIT_ACCOUNT + | I_INT + | I_ISNAT + | I_ITER + | I_JOIN_TICKETS + | I_KECCAK + | I_LAMBDA + | I_LE + | I_LEFT + | I_LEVEL + | I_LOOP + | I_LOOP_LEFT + | I_LSL + | I_LSR + | I_LT + | I_MAP + | I_MEM + | I_MUL + | I_NEG + | I_NEQ + | I_NEVER + | I_NIL + | I_NONE + | I_NOT + | I_NOW + | I_OR + | I_PACK + | I_PAIR + | I_PAIRING_CHECK + | I_PUSH + | I_READ_TICKET + | I_RENAME + | I_RIGHT + | I_SAPLING_EMPTY_STATE + | I_SAPLING_VERIFY_UPDATE + | I_SELF + | I_SELF_ADDRESS + | I_SENDER + | I_SET_DELEGATE + | I_SHA256 + | I_SHA512 + | I_SHA3 + | I_SIZE + | I_SLICE + | I_SOME + | I_SOURCE + | I_SPLIT_TICKET + | I_STEPS_TO_QUOTA + | I_SUB + | I_SWAP + | I_TICKET + | I_TOTAL_VOTING_POWER + | I_TRANSFER_TOKENS + | I_UNIT + | I_UNPACK + | I_UNPAIR + | I_UPDATE + | I_VOTING_POWER + | I_XOR -> + Instr_namespace + | T_address + | T_big_map + | T_bool + | T_bytes + | T_chain_id + | T_contract + | T_int + | T_key + | T_key_hash + | T_lambda + | T_list + | T_map + | T_mutez + | T_nat + | T_never + | T_operation + | T_option + | T_or + | T_pair + | T_sapling_state + | T_sapling_transaction + | T_set + | T_signature + | T_string + | T_timestamp + | T_unit + | T_bls12_381_fr + | T_bls12_381_g1 + | T_bls12_381_g2 + | T_ticket -> + Type_namespace + +let valid_case name = + let is_lower = function '_' | 'a' .. 'z' -> true | _ -> false in + let is_upper = function '_' | 'A' .. 'Z' -> true | _ -> false in + let rec for_all a b f = + Compare.Int.(a > b) || (f a && for_all (a + 1) b f) + in + let len = String.length name in + Compare.Int.(len <> 0) + && Compare.Char.(name.[0] <> '_') + && ( (is_upper name.[0] && for_all 1 (len - 1) (fun i -> is_upper name.[i])) + || (is_upper name.[0] && for_all 1 (len - 1) (fun i -> is_lower name.[i])) + || (is_lower name.[0] && for_all 1 (len - 1) (fun i -> is_lower name.[i])) + ) + +let string_of_prim = function + | K_parameter -> + "parameter" + | K_storage -> + "storage" + | K_code -> + "code" + | D_False -> + "False" + | D_Elt -> + "Elt" + | D_Left -> + "Left" + | D_None -> + "None" + | D_Pair -> + "Pair" + | D_Right -> + "Right" + | D_Some -> + "Some" + | D_True -> + "True" + | D_Unit -> + "Unit" + | I_PACK -> + "PACK" + | I_UNPACK -> + "UNPACK" + | I_BLAKE2B -> + "BLAKE2B" + | I_SHA256 -> + "SHA256" + | I_SHA512 -> + "SHA512" + | I_ABS -> + "ABS" + | I_ADD -> + "ADD" + | I_AMOUNT -> + "AMOUNT" + | I_AND -> + "AND" + | I_BALANCE -> + "BALANCE" + | I_CAR -> + "CAR" + | I_CDR -> + "CDR" + | I_CHAIN_ID -> + "CHAIN_ID" + | I_CHECK_SIGNATURE -> + "CHECK_SIGNATURE" + | I_COMPARE -> + "COMPARE" + | I_CONCAT -> + "CONCAT" + | I_CONS -> + "CONS" + | I_CREATE_ACCOUNT -> + "CREATE_ACCOUNT" + | I_CREATE_CONTRACT -> + "CREATE_CONTRACT" + | I_IMPLICIT_ACCOUNT -> + "IMPLICIT_ACCOUNT" + | I_DIP -> + "DIP" + | I_DROP -> + "DROP" + | I_DUP -> + "DUP" + | I_EDIV -> + "EDIV" + | I_EMPTY_BIG_MAP -> + "EMPTY_BIG_MAP" + | I_EMPTY_MAP -> + "EMPTY_MAP" + | I_EMPTY_SET -> + "EMPTY_SET" + | I_EQ -> + "EQ" + | I_EXEC -> + "EXEC" + | I_APPLY -> + "APPLY" + | I_FAILWITH -> + "FAILWITH" + | I_GE -> + "GE" + | I_GET -> + "GET" + | I_GET_AND_UPDATE -> + "GET_AND_UPDATE" + | I_GT -> + "GT" + | I_HASH_KEY -> + "HASH_KEY" + | I_IF -> + "IF" + | I_IF_CONS -> + "IF_CONS" + | I_IF_LEFT -> + "IF_LEFT" + | I_IF_NONE -> + "IF_NONE" + | I_INT -> + "INT" + | I_LAMBDA -> + "LAMBDA" + | I_LE -> + "LE" + | I_LEFT -> + "LEFT" + | I_LEVEL -> + "LEVEL" + | I_LOOP -> + "LOOP" + | I_LSL -> + "LSL" + | I_LSR -> + "LSR" + | I_LT -> + "LT" + | I_MAP -> + "MAP" + | I_MEM -> + "MEM" + | I_MUL -> + "MUL" + | I_NEG -> + "NEG" + | I_NEQ -> + "NEQ" + | I_NIL -> + "NIL" + | I_NONE -> + "NONE" + | I_NOT -> + "NOT" + | I_NOW -> + "NOW" + | I_OR -> + "OR" + | I_PAIR -> + "PAIR" + | I_PUSH -> + "PUSH" + | I_RIGHT -> + "RIGHT" + | I_SIZE -> + "SIZE" + | I_SOME -> + "SOME" + | I_SOURCE -> + "SOURCE" + | I_SENDER -> + "SENDER" + | I_SELF -> + "SELF" + | I_SELF_ADDRESS -> + "SELF_ADDRESS" + | I_SLICE -> + "SLICE" + | I_STEPS_TO_QUOTA -> + "STEPS_TO_QUOTA" + | I_SUB -> + "SUB" + | I_SWAP -> + "SWAP" + | I_TRANSFER_TOKENS -> + "TRANSFER_TOKENS" + | I_SET_DELEGATE -> + "SET_DELEGATE" + | I_UNIT -> + "UNIT" + | I_UNPAIR -> + "UNPAIR" + | I_UPDATE -> + "UPDATE" + | I_XOR -> + "XOR" + | I_ITER -> + "ITER" + | I_LOOP_LEFT -> + "LOOP_LEFT" + | I_ADDRESS -> + "ADDRESS" + | I_CONTRACT -> + "CONTRACT" + | I_ISNAT -> + "ISNAT" + | I_CAST -> + "CAST" + | I_RENAME -> + "RENAME" + | I_SAPLING_EMPTY_STATE -> + "SAPLING_EMPTY_STATE" + | I_SAPLING_VERIFY_UPDATE -> + "SAPLING_VERIFY_UPDATE" + | I_DIG -> + "DIG" + | I_DUG -> + "DUG" + | I_NEVER -> + "NEVER" + | I_VOTING_POWER -> + "VOTING_POWER" + | I_TOTAL_VOTING_POWER -> + "TOTAL_VOTING_POWER" + | I_KECCAK -> + "KECCAK" + | I_SHA3 -> + "SHA3" + | I_PAIRING_CHECK -> + "PAIRING_CHECK" + | I_TICKET -> + "TICKET" + | I_READ_TICKET -> + "READ_TICKET" + | I_SPLIT_TICKET -> + "SPLIT_TICKET" + | I_JOIN_TICKETS -> + "JOIN_TICKETS" + | T_bool -> + "bool" + | T_contract -> + "contract" + | T_int -> + "int" + | T_key -> + "key" + | T_key_hash -> + "key_hash" + | T_lambda -> + "lambda" + | T_list -> + "list" + | T_map -> + "map" + | T_big_map -> + "big_map" + | T_nat -> + "nat" + | T_option -> + "option" + | T_or -> + "or" + | T_pair -> + "pair" + | T_set -> + "set" + | T_signature -> + "signature" + | T_string -> + "string" + | T_bytes -> + "bytes" + | T_mutez -> + "mutez" + | T_timestamp -> + "timestamp" + | T_unit -> + "unit" + | T_operation -> + "operation" + | T_address -> + "address" + | T_sapling_state -> + "sapling_state" + | T_sapling_transaction -> + "sapling_transaction" + | T_chain_id -> + "chain_id" + | T_never -> + "never" + | T_bls12_381_g1 -> + "bls12_381_g1" + | T_bls12_381_g2 -> + "bls12_381_g2" + | T_bls12_381_fr -> + "bls12_381_fr" + | T_ticket -> + "ticket" + +let prim_of_string = function + | "parameter" -> + ok K_parameter + | "storage" -> + ok K_storage + | "code" -> + ok K_code + | "False" -> + ok D_False + | "Elt" -> + ok D_Elt + | "Left" -> + ok D_Left + | "None" -> + ok D_None + | "Pair" -> + ok D_Pair + | "Right" -> + ok D_Right + | "Some" -> + ok D_Some + | "True" -> + ok D_True + | "Unit" -> + ok D_Unit + | "PACK" -> + ok I_PACK + | "UNPACK" -> + ok I_UNPACK + | "BLAKE2B" -> + ok I_BLAKE2B + | "SHA256" -> + ok I_SHA256 + | "SHA512" -> + ok I_SHA512 + | "ABS" -> + ok I_ABS + | "ADD" -> + ok I_ADD + | "AMOUNT" -> + ok I_AMOUNT + | "AND" -> + ok I_AND + | "BALANCE" -> + ok I_BALANCE + | "CAR" -> + ok I_CAR + | "CDR" -> + ok I_CDR + | "CHAIN_ID" -> + ok I_CHAIN_ID + | "CHECK_SIGNATURE" -> + ok I_CHECK_SIGNATURE + | "COMPARE" -> + ok I_COMPARE + | "CONCAT" -> + ok I_CONCAT + | "CONS" -> + ok I_CONS + | "CREATE_ACCOUNT" -> + ok I_CREATE_ACCOUNT + | "CREATE_CONTRACT" -> + ok I_CREATE_CONTRACT + | "IMPLICIT_ACCOUNT" -> + ok I_IMPLICIT_ACCOUNT + | "DIP" -> + ok I_DIP + | "DROP" -> + ok I_DROP + | "DUP" -> + ok I_DUP + | "EDIV" -> + ok I_EDIV + | "EMPTY_BIG_MAP" -> + ok I_EMPTY_BIG_MAP + | "EMPTY_MAP" -> + ok I_EMPTY_MAP + | "EMPTY_SET" -> + ok I_EMPTY_SET + | "EQ" -> + ok I_EQ + | "EXEC" -> + ok I_EXEC + | "APPLY" -> + ok I_APPLY + | "FAILWITH" -> + ok I_FAILWITH + | "GE" -> + ok I_GE + | "GET" -> + ok I_GET + | "GET_AND_UPDATE" -> + ok I_GET_AND_UPDATE + | "GT" -> + ok I_GT + | "HASH_KEY" -> + ok I_HASH_KEY + | "IF" -> + ok I_IF + | "IF_CONS" -> + ok I_IF_CONS + | "IF_LEFT" -> + ok I_IF_LEFT + | "IF_NONE" -> + ok I_IF_NONE + | "INT" -> + ok I_INT + | "KECCAK" -> + ok I_KECCAK + | "LAMBDA" -> + ok I_LAMBDA + | "LE" -> + ok I_LE + | "LEFT" -> + ok I_LEFT + | "LEVEL" -> + ok I_LEVEL + | "LOOP" -> + ok I_LOOP + | "LSL" -> + ok I_LSL + | "LSR" -> + ok I_LSR + | "LT" -> + ok I_LT + | "MAP" -> + ok I_MAP + | "MEM" -> + ok I_MEM + | "MUL" -> + ok I_MUL + | "NEG" -> + ok I_NEG + | "NEQ" -> + ok I_NEQ + | "NIL" -> + ok I_NIL + | "NONE" -> + ok I_NONE + | "NOT" -> + ok I_NOT + | "NOW" -> + ok I_NOW + | "OR" -> + ok I_OR + | "PAIR" -> + ok I_PAIR + | "UNPAIR" -> + ok I_UNPAIR + | "PAIRING_CHECK" -> + ok I_PAIRING_CHECK + | "PUSH" -> + ok I_PUSH + | "RIGHT" -> + ok I_RIGHT + | "SHA3" -> + ok I_SHA3 + | "SIZE" -> + ok I_SIZE + | "SOME" -> + ok I_SOME + | "SOURCE" -> + ok I_SOURCE + | "SENDER" -> + ok I_SENDER + | "SELF" -> + ok I_SELF + | "SELF_ADDRESS" -> + ok I_SELF_ADDRESS + | "SLICE" -> + ok I_SLICE + | "STEPS_TO_QUOTA" -> + ok I_STEPS_TO_QUOTA + | "SUB" -> + ok I_SUB + | "SWAP" -> + ok I_SWAP + | "TRANSFER_TOKENS" -> + ok I_TRANSFER_TOKENS + | "SET_DELEGATE" -> + ok I_SET_DELEGATE + | "UNIT" -> + ok I_UNIT + | "UPDATE" -> + ok I_UPDATE + | "XOR" -> + ok I_XOR + | "ITER" -> + ok I_ITER + | "LOOP_LEFT" -> + ok I_LOOP_LEFT + | "ADDRESS" -> + ok I_ADDRESS + | "CONTRACT" -> + ok I_CONTRACT + | "ISNAT" -> + ok I_ISNAT + | "CAST" -> + ok I_CAST + | "RENAME" -> + ok I_RENAME + | "SAPLING_EMPTY_STATE" -> + ok I_SAPLING_EMPTY_STATE + | "SAPLING_VERIFY_UPDATE" -> + ok I_SAPLING_VERIFY_UPDATE + | "DIG" -> + ok I_DIG + | "DUG" -> + ok I_DUG + | "NEVER" -> + ok I_NEVER + | "VOTING_POWER" -> + ok I_VOTING_POWER + | "TOTAL_VOTING_POWER" -> + ok I_TOTAL_VOTING_POWER + | "TICKET" -> + ok I_TICKET + | "READ_TICKET" -> + ok I_READ_TICKET + | "SPLIT_TICKET" -> + ok I_SPLIT_TICKET + | "JOIN_TICKETS" -> + ok I_JOIN_TICKETS + | "bool" -> + ok T_bool + | "contract" -> + ok T_contract + | "int" -> + ok T_int + | "key" -> + ok T_key + | "key_hash" -> + ok T_key_hash + | "lambda" -> + ok T_lambda + | "list" -> + ok T_list + | "map" -> + ok T_map + | "big_map" -> + ok T_big_map + | "nat" -> + ok T_nat + | "option" -> + ok T_option + | "or" -> + ok T_or + | "pair" -> + ok T_pair + | "set" -> + ok T_set + | "signature" -> + ok T_signature + | "string" -> + ok T_string + | "bytes" -> + ok T_bytes + | "mutez" -> + ok T_mutez + | "timestamp" -> + ok T_timestamp + | "unit" -> + ok T_unit + | "operation" -> + ok T_operation + | "address" -> + ok T_address + | "sapling_state" -> + ok T_sapling_state + | "sapling_transaction" -> + ok T_sapling_transaction + | "chain_id" -> + ok T_chain_id + | "never" -> + ok T_never + | "bls12_381_g1" -> + ok T_bls12_381_g1 + | "bls12_381_g2" -> + ok T_bls12_381_g2 + | "bls12_381_fr" -> + ok T_bls12_381_fr + | "ticket" -> + ok T_ticket + | n -> + if valid_case n then error (Unknown_primitive_name n) + else error (Invalid_case n) + +let prims_of_strings expr = + let rec convert = function + | (Int _ | String _ | Bytes _) as expr -> + ok expr + | Prim (loc, prim, args, annot) -> + Error_monad.record_trace + (Invalid_primitive_name (expr, loc)) + (prim_of_string prim) + >>? fun prim -> + map convert args >|? fun args -> Prim (0, prim, args, annot) + | Seq (_, args) -> + map convert args >|? fun args -> Seq (0, args) + in + convert (root expr) >|? fun expr -> strip_locations expr + [@@coq_axiom "implicit type conversion for expr in the constant cases"] + +let strings_of_prims expr = + let rec convert = function + | (Int _ | String _ | Bytes _) as expr -> + expr + | Prim (_, prim, args, annot) -> + let prim = string_of_prim prim in + let args = List.map convert args in + Prim (0, prim, args, annot) + | Seq (_, args) -> + let args = List.map convert args in + Seq (0, args) + in + strip_locations (convert (root expr)) + [@@coq_axiom "implicit type conversion for expr in the constant cases"] + +let prim_encoding = + let open Data_encoding in + def "michelson.v1.primitives" + @@ string_enum + (* Add the comment below every 10 lines *) + [ (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("parameter", K_parameter); + ("storage", K_storage); + ("code", K_code); + ("False", D_False); + ("Elt", D_Elt); + ("Left", D_Left); + ("None", D_None); + ("Pair", D_Pair); + ("Right", D_Right); + ("Some", D_Some); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("True", D_True); + ("Unit", D_Unit); + ("PACK", I_PACK); + ("UNPACK", I_UNPACK); + ("BLAKE2B", I_BLAKE2B); + ("SHA256", I_SHA256); + ("SHA512", I_SHA512); + ("ABS", I_ABS); + ("ADD", I_ADD); + ("AMOUNT", I_AMOUNT); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("AND", I_AND); + ("BALANCE", I_BALANCE); + ("CAR", I_CAR); + ("CDR", I_CDR); + ("CHECK_SIGNATURE", I_CHECK_SIGNATURE); + ("COMPARE", I_COMPARE); + ("CONCAT", I_CONCAT); + ("CONS", I_CONS); + ("CREATE_ACCOUNT", I_CREATE_ACCOUNT); + ("CREATE_CONTRACT", I_CREATE_CONTRACT); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("IMPLICIT_ACCOUNT", I_IMPLICIT_ACCOUNT); + ("DIP", I_DIP); + ("DROP", I_DROP); + ("DUP", I_DUP); + ("EDIV", I_EDIV); + ("EMPTY_MAP", I_EMPTY_MAP); + ("EMPTY_SET", I_EMPTY_SET); + ("EQ", I_EQ); + ("EXEC", I_EXEC); + ("FAILWITH", I_FAILWITH); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("GE", I_GE); + ("GET", I_GET); + ("GT", I_GT); + ("HASH_KEY", I_HASH_KEY); + ("IF", I_IF); + ("IF_CONS", I_IF_CONS); + ("IF_LEFT", I_IF_LEFT); + ("IF_NONE", I_IF_NONE); + ("INT", I_INT); + ("LAMBDA", I_LAMBDA); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("LE", I_LE); + ("LEFT", I_LEFT); + ("LOOP", I_LOOP); + ("LSL", I_LSL); + ("LSR", I_LSR); + ("LT", I_LT); + ("MAP", I_MAP); + ("MEM", I_MEM); + ("MUL", I_MUL); + ("NEG", I_NEG); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("NEQ", I_NEQ); + ("NIL", I_NIL); + ("NONE", I_NONE); + ("NOT", I_NOT); + ("NOW", I_NOW); + ("OR", I_OR); + ("PAIR", I_PAIR); + ("PUSH", I_PUSH); + ("RIGHT", I_RIGHT); + ("SIZE", I_SIZE); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("SOME", I_SOME); + ("SOURCE", I_SOURCE); + ("SENDER", I_SENDER); + ("SELF", I_SELF); + ("STEPS_TO_QUOTA", I_STEPS_TO_QUOTA); + ("SUB", I_SUB); + ("SWAP", I_SWAP); + ("TRANSFER_TOKENS", I_TRANSFER_TOKENS); + ("SET_DELEGATE", I_SET_DELEGATE); + ("UNIT", I_UNIT); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("UPDATE", I_UPDATE); + ("XOR", I_XOR); + ("ITER", I_ITER); + ("LOOP_LEFT", I_LOOP_LEFT); + ("ADDRESS", I_ADDRESS); + ("CONTRACT", I_CONTRACT); + ("ISNAT", I_ISNAT); + ("CAST", I_CAST); + ("RENAME", I_RENAME); + ("bool", T_bool); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("contract", T_contract); + ("int", T_int); + ("key", T_key); + ("key_hash", T_key_hash); + ("lambda", T_lambda); + ("list", T_list); + ("map", T_map); + ("big_map", T_big_map); + ("nat", T_nat); + ("option", T_option); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("or", T_or); + ("pair", T_pair); + ("set", T_set); + ("signature", T_signature); + ("string", T_string); + ("bytes", T_bytes); + ("mutez", T_mutez); + ("timestamp", T_timestamp); + ("unit", T_unit); + ("operation", T_operation); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("address", T_address); + (* Alpha_002 addition *) + ("SLICE", I_SLICE); + (* Alpha_005 addition *) + ("DIG", I_DIG); + ("DUG", I_DUG); + ("EMPTY_BIG_MAP", I_EMPTY_BIG_MAP); + ("APPLY", I_APPLY); + ("chain_id", T_chain_id); + ("CHAIN_ID", I_CHAIN_ID); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + (* Alpha_008 addition *) + ("LEVEL", I_LEVEL); + ("SELF_ADDRESS", I_SELF_ADDRESS); + ("never", T_never); + ("NEVER", I_NEVER); + ("UNPAIR", I_UNPAIR); + ("VOTING_POWER", I_VOTING_POWER); + ("TOTAL_VOTING_POWER", I_TOTAL_VOTING_POWER); + ("KECCAK", I_KECCAK); + ("SHA3", I_SHA3); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + (* Alpha_008 addition *) + ("PAIRING_CHECK", I_PAIRING_CHECK); + ("bls12_381_g1", T_bls12_381_g1); + ("bls12_381_g2", T_bls12_381_g2); + ("bls12_381_fr", T_bls12_381_fr); + ("sapling_state", T_sapling_state); + ("sapling_transaction", T_sapling_transaction); + ("SAPLING_EMPTY_STATE", I_SAPLING_EMPTY_STATE); + ("SAPLING_VERIFY_UPDATE", I_SAPLING_VERIFY_UPDATE); + ("ticket", T_ticket); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + (* Alpha_008 addition *) + ("TICKET", I_TICKET); + ("READ_TICKET", I_READ_TICKET); + ("SPLIT_TICKET", I_SPLIT_TICKET); + ("JOIN_TICKETS", I_JOIN_TICKETS); + ("GET_AND_UPDATE", I_GET_AND_UPDATE) + (* New instructions must be added here, for backward compatibility of the encoding. *) + (* Keep the comment above at the end of the list *) + ] + +let () = + register_error_kind + `Permanent + ~id:"michelson_v1.unknown_primitive_name" + ~title:"Unknown primitive name" + ~description:"In a script or data expression, a primitive was unknown." + ~pp:(fun ppf n -> Format.fprintf ppf "Unknown primitive %s." n) + Data_encoding.(obj1 (req "wrong_primitive_name" string)) + (function Unknown_primitive_name got -> Some got | _ -> None) + (fun got -> Unknown_primitive_name got) ; + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_primitive_name_case" + ~title:"Invalid primitive name case" + ~description: + "In a script or data expression, a primitive name is neither uppercase, \ + lowercase or capitalized." + ~pp:(fun ppf n -> Format.fprintf ppf "Primitive %s has invalid case." n) + Data_encoding.(obj1 (req "wrong_primitive_name" string)) + (function Invalid_case name -> Some name | _ -> None) + (fun name -> Invalid_case name) ; + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_primitive_name" + ~title:"Invalid primitive name" + ~description: + "In a script or data expression, a primitive name is unknown or has a \ + wrong case." + ~pp:(fun ppf _ -> Format.fprintf ppf "Invalid primitive.") + Data_encoding.( + obj2 + (req + "expression" + (Micheline.canonical_encoding ~variant:"generic" string)) + (req "location" Micheline.canonical_location_encoding)) + (function + | Invalid_primitive_name (expr, loc) -> Some (expr, loc) | _ -> None) + (fun (expr, loc) -> Invalid_primitive_name (expr, loc)) + +let string_of_namespace = function + | Type_namespace -> + "T" + | Constant_namespace -> + "D" + | Instr_namespace -> + "I" + | Keyword_namespace -> + "K" diff --git a/src/proto_009_PsFLoren/lib_protocol/michelson_v1_primitives.mli b/src/proto_009_PsFLoren/lib_protocol/michelson_v1_primitives.mli new file mode 100644 index 0000000000000000000000000000000000000000..0b02822f021c92ac02a09e479bd079e6c1161c47 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/michelson_v1_primitives.mli @@ -0,0 +1,202 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += (* `Permanent *) Unknown_primitive_name of string + +type error += (* `Permanent *) Invalid_case of string + +type error += + | (* `Permanent *) + Invalid_primitive_name of + string Micheline.canonical * Micheline.canonical_location + +type prim = + | K_parameter + | K_storage + | K_code + | D_False + | D_Elt + | D_Left + | D_None + | D_Pair + | D_Right + | D_Some + | D_True + | D_Unit + | I_PACK + | I_UNPACK + | I_BLAKE2B + | I_SHA256 + | I_SHA512 + | I_ABS + | I_ADD + | I_AMOUNT + | I_AND + | I_BALANCE + | I_CAR + | I_CDR + | I_CHAIN_ID + | I_CHECK_SIGNATURE + | I_COMPARE + | I_CONCAT + | I_CONS + | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT + | I_IMPLICIT_ACCOUNT + | I_DIP + | I_DROP + | I_DUP + | I_EDIV + | I_EMPTY_BIG_MAP + | I_EMPTY_MAP + | I_EMPTY_SET + | I_EQ + | I_EXEC + | I_APPLY + | I_FAILWITH + | I_GE + | I_GET + | I_GET_AND_UPDATE + | I_GT + | I_HASH_KEY + | I_IF + | I_IF_CONS + | I_IF_LEFT + | I_IF_NONE + | I_INT + | I_LAMBDA + | I_LE + | I_LEFT + | I_LEVEL + | I_LOOP + | I_LSL + | I_LSR + | I_LT + | I_MAP + | I_MEM + | I_MUL + | I_NEG + | I_NEQ + | I_NIL + | I_NONE + | I_NOT + | I_NOW + | I_OR + | I_PAIR + | I_UNPAIR + | I_PUSH + | I_RIGHT + | I_SIZE + | I_SOME + | I_SOURCE + | I_SENDER + | I_SELF + | I_SELF_ADDRESS + | I_SLICE + | I_STEPS_TO_QUOTA + | I_SUB + | I_SWAP + | I_TRANSFER_TOKENS + | I_SET_DELEGATE + | I_UNIT + | I_UPDATE + | I_XOR + | I_ITER + | I_LOOP_LEFT + | I_ADDRESS + | I_CONTRACT + | I_ISNAT + | I_CAST + | I_RENAME + | I_SAPLING_EMPTY_STATE + | I_SAPLING_VERIFY_UPDATE + | I_DIG + | I_DUG + | I_NEVER + | I_VOTING_POWER + | I_TOTAL_VOTING_POWER + | I_KECCAK + | I_SHA3 + | I_PAIRING_CHECK + | I_TICKET + | I_READ_TICKET + | I_SPLIT_TICKET + | I_JOIN_TICKETS + | T_bool + | T_contract + | T_int + | T_key + | T_key_hash + | T_lambda + | T_list + | T_map + | T_big_map + | T_nat + | T_option + | T_or + | T_pair + | T_set + | T_signature + | T_string + | T_bytes + | T_mutez + | T_timestamp + | T_unit + | T_operation + | T_address + | T_sapling_transaction + | T_sapling_state + | T_chain_id + | T_never + | T_bls12_381_g1 + | T_bls12_381_g2 + | T_bls12_381_fr + | T_ticket + +(** Auxiliary types for error documentation. + All the prim constructor prefixes must match their namespace. *) +type namespace = + | (* prefix "T" *) Type_namespace + | (* prefix "D" *) Constant_namespace + | (* prefix "I" *) Instr_namespace + | (* prefix "K" *) Keyword_namespace + +val namespace : prim -> namespace + +val prim_encoding : prim Data_encoding.encoding + +val string_of_prim : prim -> string + +val prim_of_string : string -> prim tzresult + +val prims_of_strings : + string Micheline.canonical -> prim Micheline.canonical tzresult + +val strings_of_prims : prim Micheline.canonical -> string Micheline.canonical + +(** The string corresponds to the constructor prefix from the given namespace + (i.e. "T", "D", "I" or "K") *) +val string_of_namespace : namespace -> string diff --git a/src/proto_009_PsFLoren/lib_protocol/misc.ml b/src/proto_009_PsFLoren/lib_protocol/misc.ml new file mode 100644 index 0000000000000000000000000000000000000000..14a34bd0ef5ec3672541b677bde4b6baff8315cb --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/misc.ml @@ -0,0 +1,89 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type 'a lazyt = unit -> 'a + +type 'a lazy_list_t = LCons of 'a * 'a lazy_list_t tzresult Lwt.t lazyt + +type 'a lazy_list = 'a lazy_list_t tzresult Lwt.t + +let rec ( --> ) i j = + (* [i; i+1; ...; j] *) + if Compare.Int.(i > j) then [] else i :: (succ i --> j) + +let rec ( ---> ) i j = + (* [i; i+1; ...; j] *) + if Compare.Int32.(i > j) then [] else i :: (Int32.succ i ---> j) + +let split delim ?(limit = max_int) path = + let l = String.length path in + let rec do_slashes acc limit i = + if Compare.Int.(i >= l) then List.rev acc + else if Compare.Char.(path.[i] = delim) then do_slashes acc limit (i + 1) + else do_split acc limit i + and do_split acc limit i = + if Compare.Int.(limit <= 0) then + if Compare.Int.(i = l) then List.rev acc + else List.rev (String.sub path i (l - i) :: acc) + else do_component acc (pred limit) i i + and do_component acc limit i j = + if Compare.Int.(j >= l) then + if Compare.Int.(i = j) then List.rev acc + else List.rev (String.sub path i (j - i) :: acc) + else if Compare.Char.(path.[j] = delim) then + do_slashes (String.sub path i (j - i) :: acc) limit j + else do_component acc limit i (j + 1) + in + if Compare.Int.(limit > 0) then do_slashes [] limit 0 else [path] + [@@coq_axiom "non-top-level mutual recursion"] + +let pp_print_paragraph ppf description = + Format.fprintf + ppf + "@[%a@]" + Format.(pp_print_list ~pp_sep:pp_print_space pp_print_string) + (split ' ' description) + +let take n l = + let rec loop acc n xs = + if Compare.Int.(n <= 0) then Some (List.rev acc, xs) + else match xs with [] -> None | x :: xs -> loop (x :: acc) (n - 1) xs + in + loop [] n l + +let remove_prefix ~prefix s = + let x = String.length prefix in + let n = String.length s in + if Compare.Int.(n >= x) && Compare.String.(String.sub s 0 x = prefix) then + Some (String.sub s x (n - x)) + else None + +let rec remove_elem_from_list nb = function + | [] -> + [] + | _ :: _ as l when Compare.Int.(nb <= 0) -> + l + | _ :: tl -> + remove_elem_from_list (nb - 1) tl diff --git a/src/proto_009_PsFLoren/lib_protocol/misc.mli b/src/proto_009_PsFLoren/lib_protocol/misc.mli new file mode 100644 index 0000000000000000000000000000000000000000..fb4e07dae4f05303bab2299a817385f7a138df85 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/misc.mli @@ -0,0 +1,47 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {2 Helper functions} *) + +type 'a lazyt = unit -> 'a + +type 'a lazy_list_t = LCons of 'a * 'a lazy_list_t tzresult Lwt.t lazyt + +type 'a lazy_list = 'a lazy_list_t tzresult Lwt.t + +(** Include bounds *) +val ( --> ) : int -> int -> int list + +val ( ---> ) : Int32.t -> Int32.t -> Int32.t list + +val pp_print_paragraph : Format.formatter -> string -> unit + +val take : int -> 'a list -> ('a list * 'a list) option + +(** Some (input with [prefix] removed), if string has [prefix], else [None] *) +val remove_prefix : prefix:string -> string -> string option + +(** [remove nb list] remove the first [nb] elements from the list [list]. *) +val remove_elem_from_list : int -> 'a list -> 'a list diff --git a/src/proto_009_PsFLoren/lib_protocol/nonce_hash.ml b/src/proto_009_PsFLoren/lib_protocol/nonce_hash.ml new file mode 100644 index 0000000000000000000000000000000000000000..a79656ea8365ae8c5005ae8dc8e254d5f94eb75c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/nonce_hash.ml @@ -0,0 +1,41 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* 32 *) +let nonce_hash = "\069\220\169" (* nce(53) *) + +include Blake2B.Make + (Base58) + (struct + let name = "cycle_nonce" + + let title = "A nonce hash" + + let b58check_prefix = nonce_hash + + let size = None + end) + +let () = Base58.check_encoded_prefix b58check_encoding "nce" 53 diff --git a/src/proto_009_PsFLoren/lib_protocol/nonce_hash.mli b/src/proto_009_PsFLoren/lib_protocol/nonce_hash.mli new file mode 100644 index 0000000000000000000000000000000000000000..5e374f2a38c0b0f7da05eaa33e91932d40e49838 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/nonce_hash.mli @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include S.HASH diff --git a/src/proto_009_PsFLoren/lib_protocol/nonce_storage.ml b/src/proto_009_PsFLoren/lib_protocol/nonce_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..23a9182ed2fa5a1d76a9c1a8b5573809fca7cbfd --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/nonce_storage.ml @@ -0,0 +1,132 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Seed_repr.nonce + +type nonce = t + +let encoding = Seed_repr.nonce_encoding + +type error += + | Too_late_revelation + | Too_early_revelation + | Previously_revealed_nonce + | Unexpected_nonce + +let () = + register_error_kind + `Branch + ~id:"nonce.too_late_revelation" + ~title:"Too late nonce revelation" + ~description:"Nonce revelation happens too late" + ~pp:(fun ppf () -> + Format.fprintf ppf "This nonce cannot be revealed anymore.") + Data_encoding.unit + (function Too_late_revelation -> Some () | _ -> None) + (fun () -> Too_late_revelation) ; + register_error_kind + `Temporary + ~id:"nonce.too_early_revelation" + ~title:"Too early nonce revelation" + ~description:"Nonce revelation happens before cycle end" + ~pp:(fun ppf () -> + Format.fprintf ppf "This nonce should not yet be revealed") + Data_encoding.unit + (function Too_early_revelation -> Some () | _ -> None) + (fun () -> Too_early_revelation) ; + register_error_kind + `Branch + ~id:"nonce.previously_revealed" + ~title:"Previously revealed nonce" + ~description:"Duplicated revelation for a nonce." + ~pp:(fun ppf () -> Format.fprintf ppf "This nonce was previously revealed") + Data_encoding.unit + (function Previously_revealed_nonce -> Some () | _ -> None) + (fun () -> Previously_revealed_nonce) ; + register_error_kind + `Branch + ~id:"nonce.unexpected" + ~title:"Unexpected nonce" + ~description: + "The provided nonce is inconsistent with the committed nonce hash." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "This nonce revelation is invalid (inconsistent with the committed \ + hash)") + Data_encoding.unit + (function Unexpected_nonce -> Some () | _ -> None) + (fun () -> Unexpected_nonce) + +(* checks that the level of a revelation is not too early or too late wrt to the + current context and that a nonce has not been already revealed for that level *) +let get_unrevealed ctxt (level : Level_repr.t) = + let cur_level = Level_storage.current ctxt in + match Cycle_repr.pred cur_level.cycle with + | None -> + fail Too_early_revelation (* no revelations during cycle 0 *) + | Some revealed_cycle -> ( + if Cycle_repr.(revealed_cycle < level.Level_repr.cycle) then + fail Too_early_revelation + else if Cycle_repr.(level.Level_repr.cycle < revealed_cycle) then + fail Too_late_revelation + else + Storage.Seed.Nonce.get ctxt level + >>=? function + | Revealed _ -> + fail Previously_revealed_nonce + | Unrevealed status -> + return status ) + +let record_hash ctxt unrevealed = + let level = Level_storage.current ctxt in + Storage.Seed.Nonce.init ctxt level (Unrevealed unrevealed) + +let reveal ctxt level nonce = + get_unrevealed ctxt level + >>=? fun unrevealed -> + error_unless + (Seed_repr.check_hash nonce unrevealed.nonce_hash) + Unexpected_nonce + >>?= fun () -> Storage.Seed.Nonce.update ctxt level (Revealed nonce) + +type unrevealed = Storage.Seed.unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; + rewards : Tez_repr.t; + fees : Tez_repr.t; +} + +type status = Storage.Seed.nonce_status = + | Unrevealed of unrevealed + | Revealed of Seed_repr.nonce + +let get = Storage.Seed.Nonce.get + +let of_bytes = Seed_repr.make_nonce + +let hash = Seed_repr.hash + +let check_hash = Seed_repr.check_hash diff --git a/src/proto_009_PsFLoren/lib_protocol/nonce_storage.mli b/src/proto_009_PsFLoren/lib_protocol/nonce_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..b305053d8ad624319853319613d9463067b23b4b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/nonce_storage.mli @@ -0,0 +1,58 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Too_late_revelation + | Too_early_revelation + | Previously_revealed_nonce + | Unexpected_nonce + +type t = Seed_repr.nonce + +type nonce = t + +val encoding : nonce Data_encoding.t + +type unrevealed = Storage.Seed.unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; + rewards : Tez_repr.t; + fees : Tez_repr.t; +} + +type status = Unrevealed of unrevealed | Revealed of Seed_repr.nonce + +val get : Raw_context.t -> Level_repr.t -> status tzresult Lwt.t + +val record_hash : Raw_context.t -> unrevealed -> Raw_context.t tzresult Lwt.t + +val reveal : + Raw_context.t -> Level_repr.t -> nonce -> Raw_context.t tzresult Lwt.t + +val of_bytes : bytes -> nonce tzresult + +val hash : nonce -> Nonce_hash.t + +val check_hash : nonce -> Nonce_hash.t -> bool diff --git a/src/proto_009_PsFLoren/lib_protocol/operation_repr.ml b/src/proto_009_PsFLoren/lib_protocol/operation_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..4cda13b8f117cd6cf58ce3d94fbf22ff4012d3a0 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/operation_repr.ml @@ -0,0 +1,915 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Low level Repr. of Operations *) + +module Kind = struct + type seed_nonce_revelation = Seed_nonce_revelation_kind + + type endorsement_with_slot = Endorsement_with_slot_kind + + type double_endorsement_evidence = Double_endorsement_evidence_kind + + type double_baking_evidence = Double_baking_evidence_kind + + type activate_account = Activate_account_kind + + type endorsement = Endorsement_kind + + type proposals = Proposals_kind + + type ballot = Ballot_kind + + type reveal = Reveal_kind + + type transaction = Transaction_kind + + type origination = Origination_kind + + type delegation = Delegation_kind + + type failing_noop = Failing_noop_kind + + type 'a manager = + | Reveal_manager_kind : reveal manager + | Transaction_manager_kind : transaction manager + | Origination_manager_kind : origination manager + | Delegation_manager_kind : delegation manager +end + +type raw = Operation.t = {shell : Operation.shell_header; proto : bytes} + +let raw_encoding = Operation.encoding + +type 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; +} + +and 'kind protocol_data = { + contents : 'kind contents_list; + signature : Signature.t option; +} + +and _ contents_list = + | Single : 'kind contents -> 'kind contents_list + | Cons : + 'kind Kind.manager contents * 'rest Kind.manager contents_list + -> ('kind * 'rest) Kind.manager contents_list + +and _ contents = + | Endorsement : {level : Raw_level_repr.t} -> Kind.endorsement contents + | Seed_nonce_revelation : { + level : Raw_level_repr.t; + nonce : Seed_repr.nonce; + } + -> Kind.seed_nonce_revelation contents + | Endorsement_with_slot : { + endorsement : Kind.endorsement operation; + slot : int; + } + -> Kind.endorsement_with_slot contents + | Double_endorsement_evidence : { + op1 : Kind.endorsement operation; + op2 : Kind.endorsement operation; + slot : int; + } + -> Kind.double_endorsement_evidence contents + | Double_baking_evidence : { + bh1 : Block_header_repr.t; + bh2 : Block_header_repr.t; + } + -> Kind.double_baking_evidence contents + | Activate_account : { + id : Ed25519.Public_key_hash.t; + activation_code : Blinded_public_key_hash.activation_code; + } + -> Kind.activate_account contents + | Proposals : { + source : Signature.Public_key_hash.t; + period : int32; + proposals : Protocol_hash.t list; + } + -> Kind.proposals contents + | Ballot : { + source : Signature.Public_key_hash.t; + period : int32; + proposal : Protocol_hash.t; + ballot : Vote_repr.ballot; + } + -> Kind.ballot contents + | Failing_noop : string -> Kind.failing_noop contents + | Manager_operation : { + source : Signature.public_key_hash; + fee : Tez_repr.tez; + counter : counter; + operation : 'kind manager_operation; + gas_limit : Gas_limit_repr.Arith.integral; + storage_limit : Z.t; + } + -> 'kind Kind.manager contents + +and _ manager_operation = + | Reveal : Signature.Public_key.t -> Kind.reveal manager_operation + | Transaction : { + amount : Tez_repr.tez; + parameters : Script_repr.lazy_expr; + entrypoint : string; + destination : Contract_repr.contract; + } + -> Kind.transaction manager_operation + | Origination : { + delegate : Signature.Public_key_hash.t option; + script : Script_repr.t; + credit : Tez_repr.tez; + preorigination : Contract_repr.t option; + } + -> Kind.origination manager_operation + | Delegation : + Signature.Public_key_hash.t option + -> Kind.delegation manager_operation + +and counter = Z.t + +let manager_kind : type kind. kind manager_operation -> kind Kind.manager = + function + | Reveal _ -> + Kind.Reveal_manager_kind + | Transaction _ -> + Kind.Transaction_manager_kind + | Origination _ -> + Kind.Origination_manager_kind + | Delegation _ -> + Kind.Delegation_manager_kind + +type 'kind internal_operation = { + source : Contract_repr.contract; + operation : 'kind manager_operation; + nonce : int; +} + +type packed_manager_operation = + | Manager : 'kind manager_operation -> packed_manager_operation + +type packed_contents = Contents : 'kind contents -> packed_contents + +type packed_contents_list = + | Contents_list : 'kind contents_list -> packed_contents_list + +type packed_protocol_data = + | Operation_data : 'kind protocol_data -> packed_protocol_data + +type packed_operation = { + shell : Operation.shell_header; + protocol_data : packed_protocol_data; +} + +let pack ({shell; protocol_data} : _ operation) : packed_operation = + {shell; protocol_data = Operation_data protocol_data} + +type packed_internal_operation = + | Internal_operation : 'kind internal_operation -> packed_internal_operation + +let rec to_list = function + | Contents_list (Single o) -> + [Contents o] + | Contents_list (Cons (o, os)) -> + Contents o :: to_list (Contents_list os) + +let rec of_list = function + | [] -> + assert false + | [Contents o] -> + Contents_list (Single o) + | Contents o :: os -> ( + let (Contents_list os) = of_list os in + match (o, os) with + | (Manager_operation _, Single (Manager_operation _)) -> + Contents_list (Cons (o, os)) + | (Manager_operation _, Cons _) -> + Contents_list (Cons (o, os)) + | _ -> + Pervasives.failwith + "Operation list of length > 1 should only contains manager \ + operations." ) + +module Encoding = struct + open Data_encoding + + let case tag name args proj inj = + let open Data_encoding in + case + tag + ~title:(String.capitalize_ascii name) + (merge_objs (obj1 (req "kind" (constant name))) args) + (fun x -> match proj x with None -> None | Some x -> Some ((), x)) + (fun ((), x) -> inj x) + + module Manager_operations = struct + type 'kind case = + | MCase : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_manager_operation -> 'kind manager_operation option; + proj : 'kind manager_operation -> 'a; + inj : 'a -> 'kind manager_operation; + } + -> 'kind case + + let reveal_case = + MCase + { + tag = 0; + name = "reveal"; + encoding = obj1 (req "public_key" Signature.Public_key.encoding); + select = (function Manager (Reveal _ as op) -> Some op | _ -> None); + proj = (function Reveal pkh -> pkh); + inj = (fun pkh -> Reveal pkh); + } + + let entrypoint_encoding = + def + ~title:"entrypoint" + ~description:"Named entrypoint to a Michelson smart contract" + "entrypoint" + @@ + let builtin_case tag name = + Data_encoding.case + (Tag tag) + ~title:name + (constant name) + (fun n -> if Compare.String.(n = name) then Some () else None) + (fun () -> name) + in + union + [ builtin_case 0 "default"; + builtin_case 1 "root"; + builtin_case 2 "do"; + builtin_case 3 "set_delegate"; + builtin_case 4 "remove_delegate"; + Data_encoding.case + (Tag 255) + ~title:"named" + (Bounded.string 31) + (fun s -> Some s) + (fun s -> s) ] + + let transaction_case = + MCase + { + tag = 1; + name = "transaction"; + encoding = + obj3 + (req "amount" Tez_repr.encoding) + (req "destination" Contract_repr.encoding) + (opt + "parameters" + (obj2 + (req "entrypoint" entrypoint_encoding) + (req "value" Script_repr.lazy_expr_encoding))); + select = + (function Manager (Transaction _ as op) -> Some op | _ -> None); + proj = + (function + | Transaction {amount; destination; parameters; entrypoint} -> + let parameters = + if + Script_repr.is_unit_parameter parameters + && Compare.String.(entrypoint = "default") + then None + else Some (entrypoint, parameters) + in + (amount, destination, parameters)); + inj = + (fun (amount, destination, parameters) -> + let (entrypoint, parameters) = + match parameters with + | None -> + ("default", Script_repr.unit_parameter) + | Some (entrypoint, value) -> + (entrypoint, value) + in + Transaction {amount; destination; parameters; entrypoint}); + } + + let origination_case = + MCase + { + tag = 2; + name = "origination"; + encoding = + obj3 + (req "balance" Tez_repr.encoding) + (opt "delegate" Signature.Public_key_hash.encoding) + (req "script" Script_repr.encoding); + select = + (function Manager (Origination _ as op) -> Some op | _ -> None); + proj = + (function + | Origination + { credit; + delegate; + script; + preorigination = + _ + (* the hash is only used internally + when originating from smart + contracts, don't serialize it *) + } -> + (credit, delegate, script)); + inj = + (fun (credit, delegate, script) -> + Origination {credit; delegate; script; preorigination = None}); + } + + let delegation_case = + MCase + { + tag = 3; + name = "delegation"; + encoding = obj1 (opt "delegate" Signature.Public_key_hash.encoding); + select = + (function Manager (Delegation _ as op) -> Some op | _ -> None); + proj = (function Delegation key -> key); + inj = (fun key -> Delegation key); + } + + let encoding = + let make (MCase {tag; name; encoding; select; proj; inj}) = + case + (Tag tag) + name + encoding + (fun o -> + match select o with None -> None | Some o -> Some (proj o)) + (fun x -> Manager (inj x)) + in + union + ~tag_size:`Uint8 + [ make reveal_case; + make transaction_case; + make origination_case; + make delegation_case ] + end + + type 'b case = + | Case : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_contents -> 'b contents option; + proj : 'b contents -> 'a; + inj : 'a -> 'b contents; + } + -> 'b case + + let endorsement_encoding = obj1 (req "level" Raw_level_repr.encoding) + + let endorsement_case = + Case + { + tag = 0; + name = "endorsement"; + encoding = endorsement_encoding; + select = + (function Contents (Endorsement _ as op) -> Some op | _ -> None); + proj = (fun (Endorsement {level}) -> level); + inj = (fun level -> Endorsement {level}); + } + + let endorsement_encoding = + let make (Case {tag; name; encoding; select = _; proj; inj}) = + case (Tag tag) name encoding (fun o -> Some (proj o)) (fun x -> inj x) + in + let to_list : Kind.endorsement contents_list -> _ = function + | Single o -> + o + in + let of_list : Kind.endorsement contents -> _ = function o -> Single o in + def "inlined.endorsement" + @@ conv + (fun ({shell; protocol_data = {contents; signature}} : _ operation) -> + (shell, (contents, signature))) + (fun (shell, (contents, signature)) -> + ({shell; protocol_data = {contents; signature}} : _ operation)) + (merge_objs + Operation.shell_header_encoding + (obj2 + (req + "operations" + ( conv to_list of_list + @@ def "inlined.endorsement.contents" + @@ union [make endorsement_case] )) + (varopt "signature" Signature.encoding))) + + let seed_nonce_revelation_case = + Case + { + tag = 1; + name = "seed_nonce_revelation"; + encoding = + obj2 + (req "level" Raw_level_repr.encoding) + (req "nonce" Seed_repr.nonce_encoding); + select = + (function + | Contents (Seed_nonce_revelation _ as op) -> Some op | _ -> None); + proj = (fun (Seed_nonce_revelation {level; nonce}) -> (level, nonce)); + inj = (fun (level, nonce) -> Seed_nonce_revelation {level; nonce}); + } + + let endorsement_with_slot_case : Kind.endorsement_with_slot case = + Case + { + tag = 10; + name = "endorsement_with_slot"; + encoding = + obj2 + (req "endorsement" (dynamic_size endorsement_encoding)) + (req "slot" uint16); + select = + (function + | Contents (Endorsement_with_slot _ as op) -> Some op | _ -> None); + proj = + (fun (Endorsement_with_slot {endorsement; slot}) -> + (endorsement, slot)); + inj = + (fun (endorsement, slot) -> + Endorsement_with_slot {endorsement; slot}); + } + + let double_endorsement_evidence_case : Kind.double_endorsement_evidence case + = + Case + { + tag = 2; + name = "double_endorsement_evidence"; + encoding = + obj3 + (req "op1" (dynamic_size endorsement_encoding)) + (req "op2" (dynamic_size endorsement_encoding)) + (req "slot" uint16); + select = + (function + | Contents (Double_endorsement_evidence _ as op) -> + Some op + | _ -> + None); + proj = + (fun (Double_endorsement_evidence {op1; op2; slot}) -> + (op1, op2, slot)); + inj = + (fun (op1, op2, slot) -> + Double_endorsement_evidence {op1; op2; slot}); + } + + let double_baking_evidence_case = + Case + { + tag = 3; + name = "double_baking_evidence"; + encoding = + obj2 + (req "bh1" (dynamic_size Block_header_repr.encoding)) + (req "bh2" (dynamic_size Block_header_repr.encoding)); + select = + (function + | Contents (Double_baking_evidence _ as op) -> Some op | _ -> None); + proj = (fun (Double_baking_evidence {bh1; bh2}) -> (bh1, bh2)); + inj = (fun (bh1, bh2) -> Double_baking_evidence {bh1; bh2}); + } + + let activate_account_case = + Case + { + tag = 4; + name = "activate_account"; + encoding = + obj2 + (req "pkh" Ed25519.Public_key_hash.encoding) + (req "secret" Blinded_public_key_hash.activation_code_encoding); + select = + (function + | Contents (Activate_account _ as op) -> Some op | _ -> None); + proj = + (fun (Activate_account {id; activation_code}) -> + (id, activation_code)); + inj = + (fun (id, activation_code) -> Activate_account {id; activation_code}); + } + + let proposals_case = + Case + { + tag = 5; + name = "proposals"; + encoding = + obj3 + (req "source" Signature.Public_key_hash.encoding) + (req "period" int32) + (req "proposals" (list Protocol_hash.encoding)); + select = + (function Contents (Proposals _ as op) -> Some op | _ -> None); + proj = + (fun (Proposals {source; period; proposals}) -> + (source, period, proposals)); + inj = + (fun (source, period, proposals) -> + Proposals {source; period; proposals}); + } + + let ballot_case = + Case + { + tag = 6; + name = "ballot"; + encoding = + obj4 + (req "source" Signature.Public_key_hash.encoding) + (req "period" int32) + (req "proposal" Protocol_hash.encoding) + (req "ballot" Vote_repr.ballot_encoding); + select = (function Contents (Ballot _ as op) -> Some op | _ -> None); + proj = + (function + | Ballot {source; period; proposal; ballot} -> + (source, period, proposal, ballot)); + inj = + (fun (source, period, proposal, ballot) -> + Ballot {source; period; proposal; ballot}); + } + + let failing_noop_case = + Case + { + tag = 17; + name = "failing_noop"; + encoding = obj1 (req "arbitrary" Data_encoding.string); + select = + (function Contents (Failing_noop _ as op) -> Some op | _ -> None); + proj = (function Failing_noop message -> message); + inj = (function message -> Failing_noop message); + } + + let manager_encoding = + obj5 + (req "source" Signature.Public_key_hash.encoding) + (req "fee" Tez_repr.encoding) + (req "counter" (check_size 10 n)) + (req "gas_limit" (check_size 10 Gas_limit_repr.Arith.n_integral_encoding)) + (req "storage_limit" (check_size 10 n)) + + let extract (type kind) + (Manager_operation + {source; fee; counter; gas_limit; storage_limit; operation = _} : + kind Kind.manager contents) = + (source, fee, counter, gas_limit, storage_limit) + + let rebuild (source, fee, counter, gas_limit, storage_limit) operation = + Manager_operation + {source; fee; counter; gas_limit; storage_limit; operation} + + let make_manager_case tag (type kind) + (Manager_operations.MCase mcase : kind Manager_operations.case) = + Case + { + tag; + name = mcase.name; + encoding = merge_objs manager_encoding mcase.encoding; + select = + (function + | Contents (Manager_operation ({operation; _} as op)) -> ( + match mcase.select (Manager operation) with + | None -> + None + | Some operation -> + Some (Manager_operation {op with operation}) ) + | _ -> + None); + proj = + (function + | Manager_operation {operation; _} as op -> + (extract op, mcase.proj operation)); + inj = (fun (op, contents) -> rebuild op (mcase.inj contents)); + } + + let reveal_case = make_manager_case 107 Manager_operations.reveal_case + + let transaction_case = + make_manager_case 108 Manager_operations.transaction_case + + let origination_case = + make_manager_case 109 Manager_operations.origination_case + + let delegation_case = + make_manager_case 110 Manager_operations.delegation_case + + let contents_encoding = + let make (Case {tag; name; encoding; select; proj; inj}) = + case + (Tag tag) + name + encoding + (fun o -> match select o with None -> None | Some o -> Some (proj o)) + (fun x -> Contents (inj x)) + in + def "operation.alpha.contents" + @@ union + [ make endorsement_case; + make seed_nonce_revelation_case; + make endorsement_with_slot_case; + make double_endorsement_evidence_case; + make double_baking_evidence_case; + make activate_account_case; + make proposals_case; + make ballot_case; + make reveal_case; + make transaction_case; + make origination_case; + make delegation_case; + make failing_noop_case ] + + let contents_list_encoding = + conv to_list of_list (Variable.list contents_encoding) + + let optional_signature_encoding = + conv + (function Some s -> s | None -> Signature.zero) + (fun s -> if Signature.equal s Signature.zero then None else Some s) + Signature.encoding + + let protocol_data_encoding = + def "operation.alpha.contents_and_signature" + @@ conv + (fun (Operation_data {contents; signature}) -> + (Contents_list contents, signature)) + (fun (Contents_list contents, signature) -> + Operation_data {contents; signature}) + (obj2 + (req "contents" contents_list_encoding) + (req "signature" optional_signature_encoding)) + + let operation_encoding = + conv + (fun {shell; protocol_data} -> (shell, protocol_data)) + (fun (shell, protocol_data) -> {shell; protocol_data}) + (merge_objs Operation.shell_header_encoding protocol_data_encoding) + + let unsigned_operation_encoding = + def "operation.alpha.unsigned_operation" + @@ merge_objs + Operation.shell_header_encoding + (obj1 (req "contents" contents_list_encoding)) + + let internal_operation_encoding = + def "operation.alpha.internal_operation" + @@ conv + (fun (Internal_operation {source; operation; nonce}) -> + ((source, nonce), Manager operation)) + (fun ((source, nonce), Manager operation) -> + Internal_operation {source; operation; nonce}) + (merge_objs + (obj2 (req "source" Contract_repr.encoding) (req "nonce" uint16)) + Manager_operations.encoding) +end + +let encoding = Encoding.operation_encoding + +let contents_encoding = Encoding.contents_encoding + +let contents_list_encoding = Encoding.contents_list_encoding + +let protocol_data_encoding = Encoding.protocol_data_encoding + +let unsigned_operation_encoding = Encoding.unsigned_operation_encoding + +let internal_operation_encoding = Encoding.internal_operation_encoding + +let raw ({shell; protocol_data} : _ operation) = + let proto = + Data_encoding.Binary.to_bytes_exn + protocol_data_encoding + (Operation_data protocol_data) + in + {Operation.shell; proto} + +let acceptable_passes (op : packed_operation) = + let (Operation_data protocol_data) = op.protocol_data in + match protocol_data.contents with + | Single (Failing_noop _) -> + [] + | Single (Endorsement _) -> + [0] + | Single (Endorsement_with_slot _) -> + [0] + | Single (Proposals _) -> + [1] + | Single (Ballot _) -> + [1] + | Single (Seed_nonce_revelation _) -> + [2] + | Single (Double_endorsement_evidence _) -> + [2] + | Single (Double_baking_evidence _) -> + [2] + | Single (Activate_account _) -> + [2] + | Single (Manager_operation _) -> + [3] + | Cons _ -> + [3] + +type error += Invalid_signature (* `Permanent *) + +type error += Missing_signature (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"operation.invalid_signature" + ~title:"Invalid operation signature" + ~description: + "The operation signature is ill-formed or has been made with the wrong \ + public key" + ~pp:(fun ppf () -> Format.fprintf ppf "The operation signature is invalid") + Data_encoding.unit + (function Invalid_signature -> Some () | _ -> None) + (fun () -> Invalid_signature) ; + register_error_kind + `Permanent + ~id:"operation.missing_signature" + ~title:"Missing operation signature" + ~description: + "The operation is of a kind that must be signed, but the signature is \ + missing" + ~pp:(fun ppf () -> Format.fprintf ppf "The operation requires a signature") + Data_encoding.unit + (function Missing_signature -> Some () | _ -> None) + (fun () -> Missing_signature) + +let check_signature (type kind) key chain_id + ({shell; protocol_data} : kind operation) = + let check ~watermark contents signature = + let unsigned_operation = + Data_encoding.Binary.to_bytes_exn + unsigned_operation_encoding + (shell, contents) + in + if Signature.check ~watermark key signature unsigned_operation then Ok () + else error Invalid_signature + in + match (protocol_data.contents, protocol_data.signature) with + | (Single _, None) -> + error Missing_signature + | (Cons _, None) -> + error Missing_signature + | ((Single (Endorsement _) as contents), Some signature) -> + check + ~watermark:(Endorsement chain_id) + (Contents_list contents) + signature + | ((Single _ as contents), Some signature) -> + check ~watermark:Generic_operation (Contents_list contents) signature + | ((Cons _ as contents), Some signature) -> + check ~watermark:Generic_operation (Contents_list contents) signature + +let hash_raw = Operation.hash + +let hash (o : _ operation) = + let proto = + Data_encoding.Binary.to_bytes_exn + protocol_data_encoding + (Operation_data o.protocol_data) + in + Operation.hash {shell = o.shell; proto} + +let hash_packed (o : packed_operation) = + let proto = + Data_encoding.Binary.to_bytes_exn protocol_data_encoding o.protocol_data + in + Operation.hash {shell = o.shell; proto} + +type ('a, 'b) eq = Eq : ('a, 'a) eq + +let equal_manager_operation_kind : + type a b. a manager_operation -> b manager_operation -> (a, b) eq option = + fun op1 op2 -> + match (op1, op2) with + | (Reveal _, Reveal _) -> + Some Eq + | (Reveal _, _) -> + None + | (Transaction _, Transaction _) -> + Some Eq + | (Transaction _, _) -> + None + | (Origination _, Origination _) -> + Some Eq + | (Origination _, _) -> + None + | (Delegation _, Delegation _) -> + Some Eq + | (Delegation _, _) -> + None + +let equal_contents_kind : + type a b. a contents -> b contents -> (a, b) eq option = + fun op1 op2 -> + match (op1, op2) with + | (Endorsement _, Endorsement _) -> + Some Eq + | (Endorsement _, _) -> + None + | (Seed_nonce_revelation _, Seed_nonce_revelation _) -> + Some Eq + | (Seed_nonce_revelation _, _) -> + None + | (Endorsement_with_slot _, Endorsement_with_slot _) -> + Some Eq + | (Endorsement_with_slot _, _) -> + None + | (Double_endorsement_evidence _, Double_endorsement_evidence _) -> + Some Eq + | (Double_endorsement_evidence _, _) -> + None + | (Double_baking_evidence _, Double_baking_evidence _) -> + Some Eq + | (Double_baking_evidence _, _) -> + None + | (Activate_account _, Activate_account _) -> + Some Eq + | (Activate_account _, _) -> + None + | (Proposals _, Proposals _) -> + Some Eq + | (Proposals _, _) -> + None + | (Ballot _, Ballot _) -> + Some Eq + | (Ballot _, _) -> + None + | (Failing_noop _, Failing_noop _) -> + Some Eq + | (Failing_noop _, _) -> + None + | (Manager_operation op1, Manager_operation op2) -> ( + match equal_manager_operation_kind op1.operation op2.operation with + | None -> + None + | Some Eq -> + Some Eq ) + | (Manager_operation _, _) -> + None + +let rec equal_contents_kind_list : + type a b. a contents_list -> b contents_list -> (a, b) eq option = + fun op1 op2 -> + match (op1, op2) with + | (Single op1, Single op2) -> + equal_contents_kind op1 op2 + | (Single _, Cons _) -> + None + | (Cons _, Single _) -> + None + | (Cons (op1, ops1), Cons (op2, ops2)) -> ( + match equal_contents_kind op1 op2 with + | None -> + None + | Some Eq -> ( + match equal_contents_kind_list ops1 ops2 with + | None -> + None + | Some Eq -> + Some Eq ) ) + +let equal : type a b. a operation -> b operation -> (a, b) eq option = + fun op1 op2 -> + if not (Operation_hash.equal (hash op1) (hash op2)) then None + else + equal_contents_kind_list + op1.protocol_data.contents + op2.protocol_data.contents diff --git a/src/proto_009_PsFLoren/lib_protocol/operation_repr.mli b/src/proto_009_PsFLoren/lib_protocol/operation_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..20b3fb7ce493698c131bd00c82823a398c82f941 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/operation_repr.mli @@ -0,0 +1,281 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Low level Repr. of Operations *) + +module Kind : sig + type seed_nonce_revelation = Seed_nonce_revelation_kind + + type endorsement_with_slot = Endorsement_with_slot_kind + + type double_endorsement_evidence = Double_endorsement_evidence_kind + + type double_baking_evidence = Double_baking_evidence_kind + + type activate_account = Activate_account_kind + + type endorsement = Endorsement_kind + + type proposals = Proposals_kind + + type ballot = Ballot_kind + + type reveal = Reveal_kind + + type transaction = Transaction_kind + + type origination = Origination_kind + + type delegation = Delegation_kind + + type failing_noop = Failing_noop_kind + + type 'a manager = + | Reveal_manager_kind : reveal manager + | Transaction_manager_kind : transaction manager + | Origination_manager_kind : origination manager + | Delegation_manager_kind : delegation manager +end + +type raw = Operation.t = {shell : Operation.shell_header; proto : bytes} + +val raw_encoding : raw Data_encoding.t + +type 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; +} + +and 'kind protocol_data = { + contents : 'kind contents_list; + signature : Signature.t option; +} + +and _ contents_list = + | Single : 'kind contents -> 'kind contents_list + | Cons : + 'kind Kind.manager contents * 'rest Kind.manager contents_list + -> ('kind * 'rest) Kind.manager contents_list + +and _ contents = + | Endorsement : {level : Raw_level_repr.t} -> Kind.endorsement contents + | Seed_nonce_revelation : { + level : Raw_level_repr.t; + nonce : Seed_repr.nonce; + } + -> Kind.seed_nonce_revelation contents + | Endorsement_with_slot : { + endorsement : Kind.endorsement operation; + slot : int; + } + -> Kind.endorsement_with_slot contents + | Double_endorsement_evidence : { + op1 : Kind.endorsement operation; + op2 : Kind.endorsement operation; + slot : int; + } + -> Kind.double_endorsement_evidence contents + | Double_baking_evidence : { + bh1 : Block_header_repr.t; + bh2 : Block_header_repr.t; + } + -> Kind.double_baking_evidence contents + | Activate_account : { + id : Ed25519.Public_key_hash.t; + activation_code : Blinded_public_key_hash.activation_code; + } + -> Kind.activate_account contents + | Proposals : { + source : Signature.Public_key_hash.t; + period : int32; + proposals : Protocol_hash.t list; + } + -> Kind.proposals contents + | Ballot : { + source : Signature.Public_key_hash.t; + period : int32; + proposal : Protocol_hash.t; + ballot : Vote_repr.ballot; + } + -> Kind.ballot contents + | Failing_noop : string -> Kind.failing_noop contents + | Manager_operation : { + source : Signature.Public_key_hash.t; + fee : Tez_repr.tez; + counter : counter; + operation : 'kind manager_operation; + gas_limit : Gas_limit_repr.Arith.integral; + storage_limit : Z.t; + } + -> 'kind Kind.manager contents + +and _ manager_operation = + | Reveal : Signature.Public_key.t -> Kind.reveal manager_operation + | Transaction : { + amount : Tez_repr.tez; + parameters : Script_repr.lazy_expr; + entrypoint : string; + destination : Contract_repr.contract; + } + -> Kind.transaction manager_operation + | Origination : { + delegate : Signature.Public_key_hash.t option; + script : Script_repr.t; + credit : Tez_repr.tez; + preorigination : Contract_repr.t option; + } + -> Kind.origination manager_operation + | Delegation : + Signature.Public_key_hash.t option + -> Kind.delegation manager_operation + +and counter = Z.t + +type 'kind internal_operation = { + source : Contract_repr.contract; + operation : 'kind manager_operation; + nonce : int; +} + +type packed_manager_operation = + | Manager : 'kind manager_operation -> packed_manager_operation + +type packed_contents = Contents : 'kind contents -> packed_contents + +type packed_contents_list = + | Contents_list : 'kind contents_list -> packed_contents_list + +val of_list : packed_contents list -> packed_contents_list + +val to_list : packed_contents_list -> packed_contents list + +type packed_protocol_data = + | Operation_data : 'kind protocol_data -> packed_protocol_data + +type packed_operation = { + shell : Operation.shell_header; + protocol_data : packed_protocol_data; +} + +val pack : 'kind operation -> packed_operation + +type packed_internal_operation = + | Internal_operation : 'kind internal_operation -> packed_internal_operation + +val manager_kind : 'kind manager_operation -> 'kind Kind.manager + +val encoding : packed_operation Data_encoding.t + +val contents_encoding : packed_contents Data_encoding.t + +val contents_list_encoding : packed_contents_list Data_encoding.t + +val protocol_data_encoding : packed_protocol_data Data_encoding.t + +val unsigned_operation_encoding : + (Operation.shell_header * packed_contents_list) Data_encoding.t + +val raw : _ operation -> raw + +val hash_raw : raw -> Operation_hash.t + +val hash : _ operation -> Operation_hash.t + +val hash_packed : packed_operation -> Operation_hash.t + +val acceptable_passes : packed_operation -> int list + +type error += Missing_signature (* `Permanent *) + +type error += Invalid_signature (* `Permanent *) + +val check_signature : + Signature.Public_key.t -> Chain_id.t -> _ operation -> unit tzresult + +val internal_operation_encoding : packed_internal_operation Data_encoding.t + +type ('a, 'b) eq = Eq : ('a, 'a) eq + +val equal : 'a operation -> 'b operation -> ('a, 'b) eq option + +module Encoding : sig + type 'b case = + | Case : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_contents -> 'b contents option; + proj : 'b contents -> 'a; + inj : 'a -> 'b contents; + } + -> 'b case + + val endorsement_case : Kind.endorsement case + + val seed_nonce_revelation_case : Kind.seed_nonce_revelation case + + val endorsement_with_slot_case : Kind.endorsement_with_slot case + + val double_endorsement_evidence_case : Kind.double_endorsement_evidence case + + val double_baking_evidence_case : Kind.double_baking_evidence case + + val activate_account_case : Kind.activate_account case + + val proposals_case : Kind.proposals case + + val ballot_case : Kind.ballot case + + val failing_noop_case : Kind.failing_noop case + + val reveal_case : Kind.reveal Kind.manager case + + val transaction_case : Kind.transaction Kind.manager case + + val origination_case : Kind.origination Kind.manager case + + val delegation_case : Kind.delegation Kind.manager case + + module Manager_operations : sig + type 'b case = + | MCase : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_manager_operation -> 'kind manager_operation option; + proj : 'kind manager_operation -> 'a; + inj : 'a -> 'kind manager_operation; + } + -> 'kind case + + val reveal_case : Kind.reveal case + + val transaction_case : Kind.transaction case + + val origination_case : Kind.origination case + + val delegation_case : Kind.delegation case + end +end diff --git a/src/proto_009_PsFLoren/lib_protocol/parameters_repr.ml b/src/proto_009_PsFLoren/lib_protocol/parameters_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..d5869c641c12dbf0776ad999c556f89649045dd7 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/parameters_repr.ml @@ -0,0 +1,127 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type bootstrap_account = { + public_key_hash : Signature.Public_key_hash.t; + public_key : Signature.Public_key.t option; + amount : Tez_repr.t; +} + +type bootstrap_contract = { + delegate : Signature.Public_key_hash.t; + amount : Tez_repr.t; + script : Script_repr.t; +} + +type t = { + bootstrap_accounts : bootstrap_account list; + bootstrap_contracts : bootstrap_contract list; + commitments : Commitment_repr.t list; + constants : Constants_repr.parametric; + security_deposit_ramp_up_cycles : int option; + no_reward_cycles : int option; +} + +let bootstrap_account_encoding = + let open Data_encoding in + union + [ case + (Tag 0) + ~title:"Public_key_known" + (tup2 Signature.Public_key.encoding Tez_repr.encoding) + (function + | {public_key_hash; public_key = Some public_key; amount} -> + assert ( + Signature.Public_key_hash.equal + (Signature.Public_key.hash public_key) + public_key_hash ) ; + Some (public_key, amount) + | {public_key = None} -> + None) + (fun (public_key, amount) -> + { + public_key = Some public_key; + public_key_hash = Signature.Public_key.hash public_key; + amount; + }); + case + (Tag 1) + ~title:"Public_key_unknown" + (tup2 Signature.Public_key_hash.encoding Tez_repr.encoding) + (function + | {public_key_hash; public_key = None; amount} -> + Some (public_key_hash, amount) + | {public_key = Some _} -> + None) + (fun (public_key_hash, amount) -> + {public_key = None; public_key_hash; amount}) ] + +let bootstrap_contract_encoding = + let open Data_encoding in + conv + (fun {delegate; amount; script} -> (delegate, amount, script)) + (fun (delegate, amount, script) -> {delegate; amount; script}) + (obj3 + (req "delegate" Signature.Public_key_hash.encoding) + (req "amount" Tez_repr.encoding) + (req "script" Script_repr.encoding)) + +let encoding = + let open Data_encoding in + conv + (fun { bootstrap_accounts; + bootstrap_contracts; + commitments; + constants; + security_deposit_ramp_up_cycles; + no_reward_cycles } -> + ( ( bootstrap_accounts, + bootstrap_contracts, + commitments, + security_deposit_ramp_up_cycles, + no_reward_cycles ), + constants )) + (fun ( ( bootstrap_accounts, + bootstrap_contracts, + commitments, + security_deposit_ramp_up_cycles, + no_reward_cycles ), + constants ) -> + { + bootstrap_accounts; + bootstrap_contracts; + commitments; + constants; + security_deposit_ramp_up_cycles; + no_reward_cycles; + }) + (merge_objs + (obj5 + (req "bootstrap_accounts" (list bootstrap_account_encoding)) + (dft "bootstrap_contracts" (list bootstrap_contract_encoding) []) + (dft "commitments" (list Commitment_repr.encoding) []) + (opt "security_deposit_ramp_up_cycles" int31) + (opt "no_reward_cycles" int31)) + Constants_repr.parametric_encoding) diff --git a/src/proto_009_PsFLoren/lib_protocol/parameters_repr.mli b/src/proto_009_PsFLoren/lib_protocol/parameters_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..6f8436e719b916ed3050d6f86b4c939adc2ec7bd --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/parameters_repr.mli @@ -0,0 +1,47 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type bootstrap_account = { + public_key_hash : Signature.Public_key_hash.t; + public_key : Signature.Public_key.t option; + amount : Tez_repr.t; +} + +type bootstrap_contract = { + delegate : Signature.Public_key_hash.t; + amount : Tez_repr.t; + script : Script_repr.t; +} + +type t = { + bootstrap_accounts : bootstrap_account list; + bootstrap_contracts : bootstrap_contract list; + commitments : Commitment_repr.t list; + constants : Constants_repr.parametric; + security_deposit_ramp_up_cycles : int option; + no_reward_cycles : int option; +} + +val encoding : t Data_encoding.t diff --git a/src/proto_009_PsFLoren/lib_protocol/period_repr.ml b/src/proto_009_PsFLoren/lib_protocol/period_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..2bd3e643b8cec528ada0c1d21b2501e411d25e72 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/period_repr.ml @@ -0,0 +1,87 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Int64.t + +type period = t + +include (Compare.Int64 : Compare.S with type t := t) + +let encoding = Data_encoding.int64 + +let rpc_arg = RPC_arg.int64 + +let pp ppf v = Format.fprintf ppf "%Ld" v + +type error += (* `Permanent *) + Malformed_period | Invalid_arg + +let () = + let open Data_encoding in + (* Malformed period *) + register_error_kind + `Permanent + ~id:"malformed_period" + ~title:"Malformed period" + ~description:"Period is negative." + ~pp:(fun ppf () -> Format.fprintf ppf "Malformed period") + empty + (function Malformed_period -> Some () | _ -> None) + (fun () -> Malformed_period) ; + (* Invalid arg *) + register_error_kind + `Permanent + ~id:"invalid_arg" + ~title:"Invalid arg" + ~description:"Negative multiple of periods are not allowed." + ~pp:(fun ppf () -> Format.fprintf ppf "Invalid arg") + empty + (function Invalid_arg -> Some () | _ -> None) + (fun () -> Invalid_arg) + +let of_seconds t = + if Compare.Int64.(t >= 0L) then ok t else error Malformed_period + +let to_seconds t = t + +let of_seconds_exn t = + match of_seconds t with + | Ok t -> + t + | _ -> + invalid_arg "Period.of_seconds_exn" + +let mult i p = + (* TODO check overflow *) + if Compare.Int32.(i < 0l) then error Invalid_arg + else ok (Int64.mul (Int64.of_int32 i) p) + +let zero = of_seconds_exn 0L + +let one_second = of_seconds_exn 1L + +let one_minute = of_seconds_exn 60L + +let one_hour = of_seconds_exn 3600L diff --git a/src/proto_009_PsFLoren/lib_protocol/period_repr.mli b/src/proto_009_PsFLoren/lib_protocol/period_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..4fbd52db4507b555c498d13e82199923a0cd8d74 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/period_repr.mli @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t + +type period = t + +include Compare.S with type t := t + +val encoding : period Data_encoding.t + +val rpc_arg : period RPC_arg.t + +val pp : Format.formatter -> period -> unit + +val to_seconds : period -> int64 + +(** [of_second period] fails if period is not positive *) +val of_seconds : int64 -> period tzresult + +(** [of_second period] fails if period is not positive. + It should only be used at toplevel for constants. *) +val of_seconds_exn : int64 -> period + +val mult : int32 -> period -> period tzresult + +val zero : period + +val one_second : period + +val one_minute : period + +val one_hour : period diff --git a/src/proto_009_PsFLoren/lib_protocol/raw_context.ml b/src/proto_009_PsFLoren/lib_protocol/raw_context.ml new file mode 100644 index 0000000000000000000000000000000000000000..4328f7ca4fd0b4d69a361cc71b0e5a1f2b58d9ef --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/raw_context.ml @@ -0,0 +1,994 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Int_set = Set.Make (Compare.Int) + +(* + + Gas levels maintainance + ======================= + + The context maintains two levels of gas, one corresponds to the gas + available for the current operation while the other is the gas + available for the current block. + + When gas is consumed, we must morally decrement these two levels to + check if one of them hits zero. However, since these decrements are + the same on both levels, it is not strictly necessary to update the + two levels: we can simply maintain the minimum of both levels in a + [gas_counter]. The meaning of [gas_counter] is denoted by + [gas_counter_status]: *) + +type gas_counter_status = + (* When the operation gas is unaccounted: *) + | Unlimited_operation_gas + (* When the operation gas level is the minimum: *) + | Count_operation_gas of {block_gas_delta : Gas_limit_repr.Arith.fp} + (* When the block gas level is the minimum. *) + | Count_block_gas of {operation_gas_delta : Gas_limit_repr.Arith.fp} + +(* + In each case, we keep enough information in [gas_counter_status] to + reconstruct the level that is not represented by [gas_counter]. In + the gas [Unlimited_operation_gas], the block gas level is stored + in [gas_counter]. + + [Raw_context] interface provides two accessors for the operation + gas level and the block gas level. These accessors compute these values + on-the-fly based on the current value of [gas_counter] and + [gas_counter_status]. + + A layered context + ================= + + Updating the context [gas_counter] is a critical routine called + very frequently by the operations performed by the protocol. + On the contrary, other fields are less frequently updated. + + In a previous version of the context datatype definition, all + the fields were represented at the toplevel. To update the + [gas_counter], we had to copy ~25 fields (that is 200 bytes). + + With the following layered representation, we only have to + copy 2 fields (16 bytes) during [gas_counter] update. This + has a significant impact on the Michelson runtime efficiency. + + Here are the fields on the [back] of the context: + + *) +type back = { + context : Context.t; + constants : Constants_repr.parametric; + first_level : Raw_level_repr.t; + level : Level_repr.t; + predecessor_timestamp : Time.t; + timestamp : Time.t; + fitness : Int64.t; + deposits : Tez_repr.t Signature.Public_key_hash.Map.t; + included_endorsements : int; + allowed_endorsements : + (Signature.Public_key.t * int list * bool) Signature.Public_key_hash.Map.t; + fees : Tez_repr.t; + rewards : Tez_repr.t; + storage_space_to_pay : Z.t option; + allocated_contracts : int option; + origination_nonce : Contract_repr.origination_nonce option; + temporary_lazy_storage_ids : Lazy_storage_kind.Temp_ids.t; + internal_nonce : int; + internal_nonces_used : Int_set.t; + gas_counter_status : gas_counter_status; +} + +(* + + The context is simply a record with two fields which + limits the cost of updating the [gas_counter]. + +*) +type t = {gas_counter : Gas_limit_repr.Arith.fp; back : back} + +type root = t + +(* + + Context fields accessors + ======================== + + To have the context related code more robust to evolutions, + we introduce accessors to get and to update the context + components. + +*) +let[@inline] context ctxt = ctxt.back.context + +let[@inline] current_level ctxt = ctxt.back.level + +let[@inline] storage_space_to_pay ctxt = ctxt.back.storage_space_to_pay + +let[@inline] predecessor_timestamp ctxt = ctxt.back.predecessor_timestamp + +let[@inline] current_timestamp ctxt = ctxt.back.timestamp + +let[@inline] current_fitness ctxt = ctxt.back.fitness + +let[@inline] first_level ctxt = ctxt.back.first_level + +let[@inline] constants ctxt = ctxt.back.constants + +let[@inline] recover ctxt = ctxt.back.context + +let[@inline] fees ctxt = ctxt.back.fees + +let[@inline] origination_nonce ctxt = ctxt.back.origination_nonce + +let[@inline] deposits ctxt = ctxt.back.deposits + +let[@inline] allowed_endorsements ctxt = ctxt.back.allowed_endorsements + +let[@inline] included_endorsements ctxt = ctxt.back.included_endorsements + +let[@inline] internal_nonce ctxt = ctxt.back.internal_nonce + +let[@inline] internal_nonces_used ctxt = ctxt.back.internal_nonces_used + +let[@inline] gas_counter_status ctxt = ctxt.back.gas_counter_status + +let[@inline] rewards ctxt = ctxt.back.rewards + +let[@inline] allocated_contracts ctxt = ctxt.back.allocated_contracts + +let[@inline] temporary_lazy_storage_ids ctxt = + ctxt.back.temporary_lazy_storage_ids + +let[@inline] gas_counter ctxt = ctxt.gas_counter + +let[@inline] update_gas_counter ctxt gas_counter = {ctxt with gas_counter} + +let[@inline] update_back ctxt back = {ctxt with back} + +let[@inline] update_gas_counter_status ctxt gas_counter_status = + update_back ctxt {ctxt.back with gas_counter_status} + +let[@inline] update_context ctxt context = + update_back ctxt {ctxt.back with context} + +let[@inline] update_constants ctxt constants = + update_back ctxt {ctxt.back with constants} + +let[@inline] update_fitness ctxt fitness = + update_back ctxt {ctxt.back with fitness} + +let[@inline] update_deposits ctxt deposits = + update_back ctxt {ctxt.back with deposits} + +let[@inline] update_allowed_endorsements ctxt allowed_endorsements = + update_back ctxt {ctxt.back with allowed_endorsements} + +let[@inline] update_rewards ctxt rewards = + update_back ctxt {ctxt.back with rewards} + +let[@inline] update_storage_space_to_pay ctxt storage_space_to_pay = + update_back ctxt {ctxt.back with storage_space_to_pay} + +let[@inline] update_allocated_contracts ctxt allocated_contracts = + update_back ctxt {ctxt.back with allocated_contracts} + +let[@inline] update_origination_nonce ctxt origination_nonce = + update_back ctxt {ctxt.back with origination_nonce} + +let[@inline] update_internal_nonce ctxt internal_nonce = + update_back ctxt {ctxt.back with internal_nonce} + +let[@inline] update_internal_nonces_used ctxt internal_nonces_used = + update_back ctxt {ctxt.back with internal_nonces_used} + +let[@inline] update_included_endorsements ctxt included_endorsements = + update_back ctxt {ctxt.back with included_endorsements} + +let[@inline] update_fees ctxt fees = update_back ctxt {ctxt.back with fees} + +let[@inline] update_temporary_lazy_storage_ids ctxt temporary_lazy_storage_ids + = + update_back ctxt {ctxt.back with temporary_lazy_storage_ids} + +let record_endorsement ctxt k = + match + Signature.Public_key_hash.Map.find_opt k (allowed_endorsements ctxt) + with + | None -> + assert false + | Some (_, _, true) -> + assert false (* right already used *) + | Some (d, s, false) -> + let ctxt = + update_included_endorsements + ctxt + (included_endorsements ctxt + List.length s) + in + update_allowed_endorsements + ctxt + (Signature.Public_key_hash.Map.add + k + (d, s, true) + (allowed_endorsements ctxt)) + +let init_endorsements ctxt allowed_endorsements' = + if Signature.Public_key_hash.Map.is_empty allowed_endorsements' then + assert false (* can't initialize to empty *) + else if Signature.Public_key_hash.Map.is_empty (allowed_endorsements ctxt) + then update_allowed_endorsements ctxt allowed_endorsements' + else assert false + +type error += Too_many_internal_operations (* `Permanent *) + +type error += Block_quota_exceeded (* `Temporary *) + +type error += Operation_quota_exceeded (* `Temporary *) + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"too_many_internal_operations" + ~title:"Too many internal operations" + ~description: + "A transaction exceeded the hard limit of internal operations it can emit" + empty + (function Too_many_internal_operations -> Some () | _ -> None) + (fun () -> Too_many_internal_operations) ; + register_error_kind + `Temporary + ~id:"gas_exhausted.operation" + ~title:"Gas quota exceeded for the operation" + ~description: + "A script or one of its callee took more time than the operation said \ + it would" + empty + (function Operation_quota_exceeded -> Some () | _ -> None) + (fun () -> Operation_quota_exceeded) ; + register_error_kind + `Temporary + ~id:"gas_exhausted.block" + ~title:"Gas quota exceeded for the block" + ~description: + "The sum of gas consumed by all the operations in the block exceeds the \ + hard gas limit per block" + empty + (function Block_quota_exceeded -> Some () | _ -> None) + (fun () -> Block_quota_exceeded) + +let fresh_internal_nonce ctxt = + if Compare.Int.(internal_nonce ctxt >= 65_535) then + error Too_many_internal_operations + else + ok + ( update_internal_nonce ctxt (internal_nonce ctxt + 1), + internal_nonce ctxt ) + +let reset_internal_nonce ctxt = + let ctxt = update_internal_nonce ctxt 0 in + update_internal_nonces_used ctxt Int_set.empty + +let record_internal_nonce ctxt k = + update_internal_nonces_used ctxt (Int_set.add k (internal_nonces_used ctxt)) + +let internal_nonce_already_recorded ctxt k = + Int_set.mem k (internal_nonces_used ctxt) + +let set_current_fitness ctxt fitness = update_fitness ctxt fitness + +let add_fees ctxt fees' = Tez_repr.(fees ctxt +? fees') >|? update_fees ctxt + +let add_rewards ctxt rewards' = + Tez_repr.(rewards ctxt +? rewards') >|? update_rewards ctxt + +let add_deposit ctxt delegate deposit = + let open Signature.Public_key_hash.Map in + let previous = + match find_opt delegate (deposits ctxt) with + | Some tz -> + tz + | None -> + Tez_repr.zero + in + Tez_repr.(previous +? deposit) + >|? fun deposit -> + let deposits = add delegate deposit (deposits ctxt) in + update_deposits ctxt deposits + +let get_deposits = deposits + +let get_rewards = rewards + +let get_fees = fees + +type error += Undefined_operation_nonce (* `Permanent *) + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"undefined_operation_nonce" + ~title:"Ill timed access to the origination nonce" + ~description: + "An origination was attempted out of the scope of a manager operation" + empty + (function Undefined_operation_nonce -> Some () | _ -> None) + (fun () -> Undefined_operation_nonce) + +let init_origination_nonce ctxt operation_hash = + let origination_nonce = + Some (Contract_repr.initial_origination_nonce operation_hash) + in + update_origination_nonce ctxt origination_nonce + +let increment_origination_nonce ctxt = + match origination_nonce ctxt with + | None -> + error Undefined_operation_nonce + | Some cur_origination_nonce -> + let origination_nonce = + Some (Contract_repr.incr_origination_nonce cur_origination_nonce) + in + let ctxt = update_origination_nonce ctxt origination_nonce in + ok (ctxt, cur_origination_nonce) + +let origination_nonce ctxt = + match origination_nonce ctxt with + | None -> + error Undefined_operation_nonce + | Some origination_nonce -> + ok origination_nonce + +let unset_origination_nonce ctxt = update_origination_nonce ctxt None + +type error += Gas_limit_too_high (* `Permanent *) + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"gas_limit_too_high" + ~title:"Gas limit out of protocol hard bounds" + ~description:"A transaction tried to exceed the hard limit on gas" + empty + (function Gas_limit_too_high -> Some () | _ -> None) + (fun () -> Gas_limit_too_high) + +let gas_level ctxt = + let open Gas_limit_repr in + match gas_counter_status ctxt with + | Unlimited_operation_gas -> + Unaccounted + | Count_block_gas {operation_gas_delta} -> + Limited {remaining = Arith.(add (gas_counter ctxt) operation_gas_delta)} + | Count_operation_gas _ -> + Limited {remaining = gas_counter ctxt} + +let block_gas_level ctxt = + let open Gas_limit_repr in + match gas_counter_status ctxt with + | Unlimited_operation_gas | Count_block_gas _ -> + gas_counter ctxt + | Count_operation_gas {block_gas_delta} -> + Arith.(add (gas_counter ctxt) block_gas_delta) + +let check_gas_limit ctxt (remaining : 'a Gas_limit_repr.Arith.t) = + if + Gas_limit_repr.Arith.( + remaining > (constants ctxt).hard_gas_limit_per_operation + || remaining < zero) + then error Gas_limit_too_high + else ok_unit + +let set_gas_limit ctxt (remaining : 'a Gas_limit_repr.Arith.t) = + let open Gas_limit_repr in + let remaining = Arith.fp remaining in + let block_gas = block_gas_level ctxt in + let (gas_counter_status, gas_counter) = + if Arith.(remaining < block_gas) then + let block_gas_delta = Arith.sub block_gas remaining in + (Count_operation_gas {block_gas_delta}, remaining) + else + let operation_gas_delta = Arith.sub remaining block_gas in + (Count_block_gas {operation_gas_delta}, block_gas) + in + let ctxt = update_gas_counter_status ctxt gas_counter_status in + {ctxt with gas_counter} + +let set_gas_unlimited ctxt = + let block_gas = block_gas_level ctxt in + let ctxt = {ctxt with gas_counter = block_gas} in + update_gas_counter_status ctxt Unlimited_operation_gas + +let is_gas_unlimited ctxt = + match ctxt.back.gas_counter_status with + | Unlimited_operation_gas -> + true + | _ -> + false + +let is_counting_block_gas ctxt = + match gas_counter_status ctxt with Count_block_gas _ -> true | _ -> false + +let consume_gas ctxt cost = + if is_gas_unlimited ctxt then ok ctxt + else + match Gas_limit_repr.raw_consume (gas_counter ctxt) cost with + | Some gas_counter -> + Ok (update_gas_counter ctxt gas_counter) + | None -> + if is_counting_block_gas ctxt then error Block_quota_exceeded + else error Operation_quota_exceeded + +let check_enough_gas ctxt cost = consume_gas ctxt cost >>? fun _ -> ok_unit + +let gas_consumed ~since ~until = + match (gas_level since, gas_level until) with + | (Limited {remaining = before}, Limited {remaining = after}) -> + Gas_limit_repr.Arith.sub before after + | (_, _) -> + Gas_limit_repr.Arith.zero + +let init_storage_space_to_pay ctxt = + match storage_space_to_pay ctxt with + | Some _ -> + assert false + | None -> + let ctxt = update_storage_space_to_pay ctxt (Some Z.zero) in + update_allocated_contracts ctxt (Some 0) + +let clear_storage_space_to_pay ctxt = + match (storage_space_to_pay ctxt, allocated_contracts ctxt) with + | (None, _) | (_, None) -> + assert false + | (Some storage_space_to_pay, Some allocated_contracts) -> + let ctxt = update_storage_space_to_pay ctxt None in + let ctxt = update_allocated_contracts ctxt None in + (ctxt, storage_space_to_pay, allocated_contracts) + +let update_storage_space_to_pay ctxt n = + match storage_space_to_pay ctxt with + | None -> + assert false + | Some storage_space_to_pay -> + update_storage_space_to_pay ctxt (Some (Z.add n storage_space_to_pay)) + +let update_allocated_contracts_count ctxt = + match allocated_contracts ctxt with + | None -> + assert false + | Some allocated_contracts -> + update_allocated_contracts ctxt (Some (succ allocated_contracts)) + +type missing_key_kind = Get | Set | Del | Copy + +type storage_error = + | Incompatible_protocol_version of string + | Missing_key of string list * missing_key_kind + | Existing_key of string list + | Corrupted_data of string list + +let storage_error_encoding = + let open Data_encoding in + union + [ case + (Tag 0) + ~title:"Incompatible_protocol_version" + (obj1 (req "incompatible_protocol_version" string)) + (function Incompatible_protocol_version arg -> Some arg | _ -> None) + (fun arg -> Incompatible_protocol_version arg); + case + (Tag 1) + ~title:"Missing_key" + (obj2 + (req "missing_key" (list string)) + (req + "function" + (string_enum + [("get", Get); ("set", Set); ("del", Del); ("copy", Copy)]))) + (function Missing_key (key, f) -> Some (key, f) | _ -> None) + (fun (key, f) -> Missing_key (key, f)); + case + (Tag 2) + ~title:"Existing_key" + (obj1 (req "existing_key" (list string))) + (function Existing_key key -> Some key | _ -> None) + (fun key -> Existing_key key); + case + (Tag 3) + ~title:"Corrupted_data" + (obj1 (req "corrupted_data" (list string))) + (function Corrupted_data key -> Some key | _ -> None) + (fun key -> Corrupted_data key) ] + +let pp_storage_error ppf = function + | Incompatible_protocol_version version -> + Format.fprintf + ppf + "Found a context with an unexpected version '%s'." + version + | Missing_key (key, Get) -> + Format.fprintf ppf "Missing key '%s'." (String.concat "/" key) + | Missing_key (key, Set) -> + Format.fprintf + ppf + "Cannot set undefined key '%s'." + (String.concat "/" key) + | Missing_key (key, Del) -> + Format.fprintf + ppf + "Cannot delete undefined key '%s'." + (String.concat "/" key) + | Missing_key (key, Copy) -> + Format.fprintf + ppf + "Cannot copy undefined key '%s'." + (String.concat "/" key) + | Existing_key key -> + Format.fprintf + ppf + "Cannot initialize defined key '%s'." + (String.concat "/" key) + | Corrupted_data key -> + Format.fprintf + ppf + "Failed to parse the data at '%s'." + (String.concat "/" key) + +type error += Storage_error of storage_error + +let () = + register_error_kind + `Permanent + ~id:"context.storage_error" + ~title:"Storage error (fatal internal error)" + ~description: + "An error that should never happen unless something has been deleted or \ + corrupted in the database." + ~pp:(fun ppf err -> + Format.fprintf ppf "@[Storage error:@ %a@]" pp_storage_error err) + storage_error_encoding + (function Storage_error err -> Some err | _ -> None) + (fun err -> Storage_error err) + +let storage_error err = error (Storage_error err) + +(* Initialization *********************************************************) + +(* This key should always be populated for every version of the + protocol. It's absence meaning that the context is empty. *) +let version_key = ["version"] + +(* This value is set by the snapshot_alpha.sh script, don't change it. *) +let version_value = "florence_009" + +let version = "v1" + +let first_level_key = [version; "first_level"] + +let constants_key = [version; "constants"] + +let protocol_param_key = ["protocol_parameters"] + +let get_first_level ctxt = + Context.find ctxt first_level_key + >|= function + | None -> + storage_error (Missing_key (first_level_key, Get)) + | Some bytes -> ( + match Data_encoding.Binary.of_bytes Raw_level_repr.encoding bytes with + | None -> + storage_error (Corrupted_data first_level_key) + | Some level -> + ok level ) + +let set_first_level ctxt level = + let bytes = + Data_encoding.Binary.to_bytes_exn Raw_level_repr.encoding level + in + Context.add ctxt first_level_key bytes >|= ok + +type error += Failed_to_parse_parameter of bytes + +type error += Failed_to_decode_parameter of Data_encoding.json * string + +let () = + register_error_kind + `Temporary + ~id:"context.failed_to_parse_parameter" + ~title:"Failed to parse parameter" + ~description:"The protocol parameters are not valid JSON." + ~pp:(fun ppf bytes -> + Format.fprintf + ppf + "@[Cannot parse the protocol parameter:@ %s@]" + (Bytes.to_string bytes)) + Data_encoding.(obj1 (req "contents" bytes)) + (function Failed_to_parse_parameter data -> Some data | _ -> None) + (fun data -> Failed_to_parse_parameter data) ; + register_error_kind + `Temporary + ~id:"context.failed_to_decode_parameter" + ~title:"Failed to decode parameter" + ~description:"Unexpected JSON object." + ~pp:(fun ppf (json, msg) -> + Format.fprintf + ppf + "@[Cannot decode the protocol parameter:@ %s@ %a@]" + msg + Data_encoding.Json.pp + json) + Data_encoding.(obj2 (req "contents" json) (req "error" string)) + (function + | Failed_to_decode_parameter (json, msg) -> Some (json, msg) | _ -> None) + (fun (json, msg) -> Failed_to_decode_parameter (json, msg)) + +let get_proto_param ctxt = + Context.find ctxt protocol_param_key + >>= function + | None -> + failwith "Missing protocol parameters." + | Some bytes -> ( + match Data_encoding.Binary.of_bytes Data_encoding.json bytes with + | None -> + fail (Failed_to_parse_parameter bytes) + | Some json -> ( + Context.remove ctxt protocol_param_key + >|= fun ctxt -> + match Data_encoding.Json.destruct Parameters_repr.encoding json with + | exception (Data_encoding.Json.Cannot_destruct _ as exn) -> + Format.kasprintf + failwith + "Invalid protocol_parameters: %a %a" + (fun ppf -> Data_encoding.Json.print_error ppf) + exn + Data_encoding.Json.pp + json + | param -> + ok (param, ctxt) ) ) + +let add_constants ctxt constants = + let bytes = + Data_encoding.Binary.to_bytes_exn + Constants_repr.parametric_encoding + constants + in + Context.add ctxt constants_key bytes + +let get_constants ctxt = + Context.find ctxt constants_key + >|= function + | None -> + failwith "Internal error: cannot read constants in context." + | Some bytes -> ( + match + Data_encoding.Binary.of_bytes Constants_repr.parametric_encoding bytes + with + | None -> + failwith "Internal error: cannot parse constants in context." + | Some constants -> + ok constants ) + +let patch_constants ctxt f = + let constants = f (constants ctxt) in + add_constants (context ctxt) constants + >|= fun context -> + let ctxt = update_context ctxt context in + update_constants ctxt constants + +let check_inited ctxt = + Context.find ctxt version_key + >|= function + | None -> + failwith "Internal error: un-initialized context." + | Some bytes -> + let s = Bytes.to_string bytes in + if Compare.String.(s = version_value) then ok_unit + else storage_error (Incompatible_protocol_version s) + +let prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt = + Raw_level_repr.of_int32 level + >>?= fun level -> + Fitness_repr.to_int64 fitness + >>?= fun fitness -> + check_inited ctxt + >>=? fun () -> + get_constants ctxt + >>=? fun constants -> + get_first_level ctxt + >|=? fun first_level -> + let level = + Level_repr.level_from_raw + ~first_level + ~blocks_per_cycle:constants.Constants_repr.blocks_per_cycle + ~blocks_per_commitment:constants.Constants_repr.blocks_per_commitment + level + in + { + gas_counter = + Gas_limit_repr.Arith.fp constants.Constants_repr.hard_gas_limit_per_block; + back = + { + context = ctxt; + constants; + level; + predecessor_timestamp; + timestamp; + fitness; + first_level; + allowed_endorsements = Signature.Public_key_hash.Map.empty; + included_endorsements = 0; + fees = Tez_repr.zero; + rewards = Tez_repr.zero; + deposits = Signature.Public_key_hash.Map.empty; + storage_space_to_pay = None; + allocated_contracts = None; + origination_nonce = None; + temporary_lazy_storage_ids = Lazy_storage_kind.Temp_ids.init; + internal_nonce = 0; + internal_nonces_used = Int_set.empty; + gas_counter_status = Unlimited_operation_gas; + }; + } + +type previous_protocol = Genesis of Parameters_repr.t | Edo_008 + +let check_and_update_protocol_version ctxt = + Context.find ctxt version_key + >>= (function + | None -> + failwith + "Internal error: un-initialized context in check_first_block." + | Some bytes -> + let s = Bytes.to_string bytes in + if Compare.String.(s = version_value) then + failwith "Internal error: previously initialized context." + else if Compare.String.(s = "genesis") then + get_proto_param ctxt + >|=? fun (param, ctxt) -> (Genesis param, ctxt) + else if Compare.String.(s = "edo_008") then return (Edo_008, ctxt) + else Lwt.return @@ storage_error (Incompatible_protocol_version s)) + >>=? fun (previous_proto, ctxt) -> + Context.add ctxt version_key (Bytes.of_string version_value) + >|= fun ctxt -> ok (previous_proto, ctxt) + +let prepare_first_block ~level ~timestamp ~fitness ctxt = + check_and_update_protocol_version ctxt + >>=? fun (previous_proto, ctxt) -> + ( match previous_proto with + | Genesis param -> + Raw_level_repr.of_int32 level + >>?= fun first_level -> + set_first_level ctxt first_level + >>=? fun ctxt -> add_constants ctxt param.constants >|= ok + | Edo_008 -> + return ctxt ) + >>=? fun ctxt -> + prepare ctxt ~level ~predecessor_timestamp:timestamp ~timestamp ~fitness + >|=? fun ctxt -> (previous_proto, ctxt) + +let activate ctxt h = Updater.activate (context ctxt) h >|= update_context ctxt + +(* Generic context ********************************************************) + +type key = string list + +type value = bytes + +type tree = Context.tree + +module type T = + Raw_context_intf.T + with type root := root + and type key := key + and type value := value + and type tree := tree + +let mem ctxt k = Context.mem (context ctxt) k + +let mem_tree ctxt k = Context.mem_tree (context ctxt) k + +let get ctxt k = + Context.find (context ctxt) k + >|= function None -> storage_error (Missing_key (k, Get)) | Some v -> ok v + +let get_tree ctxt k = + Context.find_tree (context ctxt) k + >|= function None -> storage_error (Missing_key (k, Get)) | Some v -> ok v + +let find ctxt k = Context.find (context ctxt) k + +let find_tree ctxt k = Context.find_tree (context ctxt) k + +let add ctxt k v = Context.add (context ctxt) k v >|= update_context ctxt + +let add_tree ctxt k v = + Context.add_tree (context ctxt) k v >|= update_context ctxt + +let init ctxt k v = + Context.mem (context ctxt) k + >>= function + | true -> + Lwt.return @@ storage_error (Existing_key k) + | _ -> + Context.add (context ctxt) k v + >|= fun context -> ok (update_context ctxt context) + +let init_tree ctxt k v : _ tzresult Lwt.t = + Context.mem_tree (context ctxt) k + >>= function + | true -> + Lwt.return @@ storage_error (Existing_key k) + | _ -> + Context.add_tree (context ctxt) k v + >|= fun context -> ok (update_context ctxt context) + +let update ctxt k v = + Context.mem (context ctxt) k + >>= function + | false -> + Lwt.return @@ storage_error (Missing_key (k, Set)) + | _ -> + Context.add (context ctxt) k v + >|= fun context -> ok (update_context ctxt context) + +let update_tree ctxt k v = + Context.mem_tree (context ctxt) k + >>= function + | false -> + Lwt.return @@ storage_error (Missing_key (k, Set)) + | _ -> + Context.add_tree (context ctxt) k v + >|= fun context -> ok (update_context ctxt context) + +(* Verify that the key is present before deleting *) +let remove_existing ctxt k = + Context.mem (context ctxt) k + >>= function + | false -> + Lwt.return @@ storage_error (Missing_key (k, Del)) + | _ -> + Context.remove (context ctxt) k + >|= fun context -> ok (update_context ctxt context) + +(* Verify that the key is present before deleting *) +let remove_existing_tree ctxt k = + Context.mem_tree (context ctxt) k + >>= function + | false -> + Lwt.return @@ storage_error (Missing_key (k, Del)) + | _ -> + Context.remove (context ctxt) k + >|= fun context -> ok (update_context ctxt context) + +(* Do not verify before deleting *) +let remove ctxt k = Context.remove (context ctxt) k >|= update_context ctxt + +let add_or_remove ctxt k = function + | None -> + remove ctxt k + | Some v -> + add ctxt k v + +let add_or_remove_tree ctxt k = function + | None -> + remove ctxt k + | Some v -> + add_tree ctxt k v + +let list ctxt ?offset ?length k = Context.list (context ctxt) ?offset ?length k + +let fold ?depth ctxt k ~init ~f = Context.fold ?depth (context ctxt) k ~init ~f + +module Tree = struct + include Context.Tree + + let empty ctxt = Context.Tree.empty (context ctxt) + + let get t k = + find t k + >|= function + | None -> storage_error (Missing_key (k, Get)) | Some v -> ok v + + let get_tree t k = + find_tree t k + >|= function + | None -> storage_error (Missing_key (k, Get)) | Some v -> ok v + + let init t k v = + mem t k + >>= function + | true -> + Lwt.return @@ storage_error (Existing_key k) + | _ -> + add t k v >|= ok + + let init_tree t k v = + mem_tree t k + >>= function + | true -> + Lwt.return @@ storage_error (Existing_key k) + | _ -> + add_tree t k v >|= ok + + let update t k v = + mem t k + >>= function + | false -> + Lwt.return @@ storage_error (Missing_key (k, Set)) + | _ -> + add t k v >|= ok + + let update_tree t k v = + mem_tree t k + >>= function + | false -> + Lwt.return @@ storage_error (Missing_key (k, Set)) + | _ -> + add_tree t k v >|= ok + + (* Verify that the key is present before deleting *) + let remove_existing t k = + mem t k + >>= function + | false -> + Lwt.return @@ storage_error (Missing_key (k, Del)) + | _ -> + remove t k >|= ok + + (* Verify that the key is present before deleting *) + let remove_existing_tree t k = + mem_tree t k + >>= function + | false -> + Lwt.return @@ storage_error (Missing_key (k, Del)) + | _ -> + remove t k >|= ok + + let add_or_remove t k = function None -> remove t k | Some v -> add t k v + + let add_or_remove_tree t k = function + | None -> + remove t k + | Some v -> + add_tree t k v +end + +let project x = x + +let absolute_key _ k = k + +let description = Storage_description.create () + +let fold_map_temporary_lazy_storage_ids ctxt f = + f (temporary_lazy_storage_ids ctxt) + |> fun (temporary_lazy_storage_ids, x) -> + (update_temporary_lazy_storage_ids ctxt temporary_lazy_storage_ids, x) + +let map_temporary_lazy_storage_ids_s ctxt f = + f (temporary_lazy_storage_ids ctxt) + >|= fun (ctxt, temporary_lazy_storage_ids) -> + update_temporary_lazy_storage_ids ctxt temporary_lazy_storage_ids diff --git a/src/proto_009_PsFLoren/lib_protocol/raw_context.mli b/src/proto_009_PsFLoren/lib_protocol/raw_context.mli new file mode 100644 index 0000000000000000000000000000000000000000..50e40c91793da4d0e1c97b3d6c0a8318a9b53fd8 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/raw_context.mli @@ -0,0 +1,207 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {1 Errors} *) + +type error += Too_many_internal_operations (* `Permanent *) + +type missing_key_kind = Get | Set | Del | Copy + +(** An internal storage error that should not happen *) +type storage_error = + | Incompatible_protocol_version of string + | Missing_key of string list * missing_key_kind + | Existing_key of string list + | Corrupted_data of string list + +type error += Storage_error of storage_error + +type error += Failed_to_parse_parameter of bytes + +type error += Failed_to_decode_parameter of Data_encoding.json * string + +val storage_error : storage_error -> 'a tzresult + +(** {1 Abstract Context} *) + +(** Abstract view of the context. + Includes a handle to the functional key-value database + ({!Context.t}) along with some in-memory values (gas, etc.). *) +type t + +type root = t + +(** Retrieves the state of the database and gives its abstract view. + It also returns wether this is the first block validated + with this version of the protocol. *) +val prepare : + level:Int32.t -> + predecessor_timestamp:Time.t -> + timestamp:Time.t -> + fitness:Fitness.t -> + Context.t -> + t tzresult Lwt.t + +type previous_protocol = Genesis of Parameters_repr.t | Edo_008 + +val prepare_first_block : + level:int32 -> + timestamp:Time.t -> + fitness:Fitness.t -> + Context.t -> + (previous_protocol * t) tzresult Lwt.t + +val activate : t -> Protocol_hash.t -> t Lwt.t + +(** Returns the state of the database resulting of operations on its + abstract view *) +val recover : t -> Context.t + +val current_level : t -> Level_repr.t + +val predecessor_timestamp : t -> Time.t + +val current_timestamp : t -> Time.t + +val current_fitness : t -> Int64.t + +val set_current_fitness : t -> Int64.t -> t + +val constants : t -> Constants_repr.parametric + +val patch_constants : + t -> (Constants_repr.parametric -> Constants_repr.parametric) -> t Lwt.t + +val first_level : t -> Raw_level_repr.t + +(** Increment the current block fee stash that will be credited to baker's + frozen_fees account at finalize_application *) +val add_fees : t -> Tez_repr.t -> t tzresult + +(** Increment the current block reward stash that will be credited to baker's + frozen_fees account at finalize_application *) +val add_rewards : t -> Tez_repr.t -> t tzresult + +(** Increment the current block deposit stash for a specific delegate. All the + delegates' frozen_deposit accounts are credited at finalize_application *) +val add_deposit : t -> Signature.Public_key_hash.t -> Tez_repr.t -> t tzresult + +val get_fees : t -> Tez_repr.t + +val get_rewards : t -> Tez_repr.t + +val get_deposits : t -> Tez_repr.t Signature.Public_key_hash.Map.t + +type error += Gas_limit_too_high (* `Permanent *) + +val check_gas_limit : t -> 'a Gas_limit_repr.Arith.t -> unit tzresult + +val set_gas_limit : t -> 'a Gas_limit_repr.Arith.t -> t + +val set_gas_unlimited : t -> t + +val gas_level : t -> Gas_limit_repr.t + +val gas_consumed : since:t -> until:t -> Gas_limit_repr.Arith.fp + +val block_gas_level : t -> Gas_limit_repr.Arith.fp + +val init_storage_space_to_pay : t -> t + +val update_storage_space_to_pay : t -> Z.t -> t + +val update_allocated_contracts_count : t -> t + +val clear_storage_space_to_pay : t -> t * Z.t * int + +type error += Undefined_operation_nonce (* `Permanent *) + +val init_origination_nonce : t -> Operation_hash.t -> t + +val origination_nonce : t -> Contract_repr.origination_nonce tzresult + +val increment_origination_nonce : + t -> (t * Contract_repr.origination_nonce) tzresult + +val unset_origination_nonce : t -> t + +(** {1 Generic accessors} *) + +type key = string list + +type value = bytes + +type tree + +module type T = + Raw_context_intf.T + with type root := root + and type key := key + and type value := value + and type tree := tree + +include T with type t := t + +(** Initialize the local nonce used for preventing a script to + duplicate an internal operation to replay it. *) +val reset_internal_nonce : t -> t + +(** Increments the internal operation nonce. *) +val fresh_internal_nonce : t -> (t * int) tzresult + +(** Mark an internal operation nonce as taken. *) +val record_internal_nonce : t -> int -> t + +(** Check is the internal operation nonce has been taken. *) +val internal_nonce_already_recorded : t -> int -> bool + +(** Returns a map where to each endorser's pkh is associated the list of its + endorsing slots (in increasing order) for a given level. *) +val allowed_endorsements : + t -> + (Signature.Public_key.t * int list * bool) Signature.Public_key_hash.Map.t + +(** Keep track of the number of endorsements that are included in a block *) +val included_endorsements : t -> int + +(** Initializes the map of allowed endorsements, this function must only be + called once. *) +val init_endorsements : + t -> + (Signature.Public_key.t * int list * bool) Signature.Public_key_hash.Map.t -> + t + +(** Marks an endorsement in the map as used. *) +val record_endorsement : t -> Signature.Public_key_hash.t -> t + +val fold_map_temporary_lazy_storage_ids : + t -> + (Lazy_storage_kind.Temp_ids.t -> Lazy_storage_kind.Temp_ids.t * 'res) -> + t * 'res + +val map_temporary_lazy_storage_ids_s : + t -> + (Lazy_storage_kind.Temp_ids.t -> (t * Lazy_storage_kind.Temp_ids.t) Lwt.t) -> + t Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/raw_context_intf.ml b/src/proto_009_PsFLoren/lib_protocol/raw_context_intf.ml new file mode 100644 index 0000000000000000000000000000000000000000..c2e095ec9ea623cd894b537b39eb85f91fdc8a33 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/raw_context_intf.ml @@ -0,0 +1,259 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2018-2021 Tarides *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** All context manipulation functions. This signature is included + as-is for direct context accesses, and used in {!Storage_functors} + to provide restricted views to the context. *) + +module type VIEW = sig + (* Same as [Environment_context.VIEW] but with extra getters and + setters functions. *) + + (** The type for context handler. *) + type t + + (** The type for context trees. *) + type tree + + (** The type for context keys. *) + type key = string list + + (** The type for context values. *) + type value = bytes + + (** {2 Getters} *) + + (** [mem t k] is an Lwt promise that resolves to [true] iff [k] is bound + to a value in [t]. *) + val mem : t -> key -> bool Lwt.t + + (** [mem_tree t k] is like {!mem} but for trees. *) + val mem_tree : t -> key -> bool Lwt.t + + (** [get t k] is an Lwt promise that resolves to [Ok v] if [k] is + bound to the value [v] in [t] and {!Storage_Error Missing_key} + otherwise. *) + val get : t -> key -> value tzresult Lwt.t + + (** [get_tree] is like {!get} but for trees. *) + val get_tree : t -> key -> tree tzresult Lwt.t + + (** [find t k] is an Lwt promise that resolves to [Some v] if [k] is + bound to the value [v] in [t] and [None] otherwise. *) + val find : t -> key -> value option Lwt.t + + (** [find_tree t k] is like {!find} but for trees. *) + val find_tree : t -> key -> tree option Lwt.t + + (** [list t key] is the list of files and sub-nodes stored under [k] in [t]. + The result order is not specified but is stable. + + [offset] and [length] are used for pagination. *) + val list : + t -> ?offset:int -> ?length:int -> key -> (string * tree) list Lwt.t + + (** {2 Setters} *) + + (** [init t k v] is an Lwt promise that resolves to [Ok c] if: + + - [k] is unbound in [t]; + - [k] is bound to [v] in [c]; + - and [c] is similar to [t] otherwise. + + It is {!Storage_error Existing_key} if [k] is already bound in [t]. *) + val init : t -> key -> value -> t tzresult Lwt.t + + (** [init_tree] is like {!init} but for trees. *) + val init_tree : t -> key -> tree -> t tzresult Lwt.t + + (** [update t k v] is an Lwt promise that resolves to [Ok c] if: + + - [k] is bound in [t]; + - [k] is bound to [v] in [c]; + - and [c] is similar to [t] otherwise. + + It is {!Storage_error Missing_key} if [k] is not already bound in [t]. *) + val update : t -> key -> value -> t tzresult Lwt.t + + (** [update_tree] is like {!update} but for trees. *) + val update_tree : t -> key -> tree -> t tzresult Lwt.t + + (** [add t k v] is an Lwt promise that resolves to [c] such that: + + - [k] is bound to [v] in [c]; + - and [c] is similar to [t] otherwise. + + If [k] was already bound in [t] to a value that is physically equal + to [v], the result of the function is a promise that resolves to + [t]. Otherwise, the previous binding of [k] in [t] disappears. *) + val add : t -> key -> value -> t Lwt.t + + (** [add_tree] is like {!add} but for trees. *) + val add_tree : t -> key -> tree -> t Lwt.t + + (** [remove t k v] is an Lwt promise that resolves to [c] such that: + + - [k] is unbound in [c]; + - and [c] is similar to [t] otherwise. *) + val remove : t -> key -> t Lwt.t + + (** [remove_existing t k v] is an Lwt promise that resolves to [Ok c] if: + + - [k] is bound in [t] to a value; + - [k] is unbound in [c]; + - and [c] is similar to [t] otherwise.*) + val remove_existing : t -> key -> t tzresult Lwt.t + + (** [remove_existing_tree t k v] is an Lwt promise that reolves to [Ok c] if: + + - [k] is bound in [t] to a tree; + - [k] is unbound in [c]; + - and [c] is similar to [t] otherwise.*) + val remove_existing_tree : t -> key -> t tzresult Lwt.t + + (** [add_or_remove t k v] is: + + - [add t k x] if [v] is [Some x]; + - [remove t k] otherwise. *) + val add_or_remove : t -> key -> value option -> t Lwt.t + + (** [add_or_remove_tree t k v] is: + + - [add_tree t k x] if [v] is [Some x]; + - [remove t k] otherwise. *) + val add_or_remove_tree : t -> key -> tree option -> t Lwt.t + + (** {2 Folds} *) + + (** [fold ?depth t root ~init ~f] recursively folds over the trees + and values of [t]. The [f] callbacks are called with a key relative + to [root]. [f] is never called with an empty key for values; i.e., + folding over a value is a no-op. + + Elements are traversed in lexical order of keys. + + The depth is 0-indexed. If [depth] is set (by default it is not), then [f] + is only called when the conditions described by the parameter is true: + + - [Eq d] folds over nodes and contents of depth exactly [d]. + - [Lt d] folds over nodes and contents of depth strictly less than [d]. + - [Le d] folds over nodes and contents of depth less than or equal to [d]. + - [Gt d] folds over nodes and contents of depth strictly more than [d]. + - [Ge d] folds over nodes and contents of depth more than or equal to [d]. *) + val fold : + ?depth:[`Eq of int | `Le of int | `Lt of int | `Ge of int | `Gt of int] -> + t -> + key -> + init:'a -> + f:(key -> tree -> 'a -> 'a Lwt.t) -> + 'a Lwt.t +end + +module type TREE = sig + (** [Tree] provides immutable, in-memory partial mirror of the + context, with lazy reads and delayed writes. The trees are Merkle + trees that carry the same hash as the part of the context they + mirror. + + Trees are immutable and non-persistent (they disappear if the + host crash), held in memory for efficiency, where reads are done + lazily and writes are done only when needed, e.g. on + [Context.commit]. If a key is modified twice, only the last + value will be written to disk on commit. *) + + (** The type for context views. *) + type t + + (** The type for context trees. *) + type tree + + include VIEW with type t := tree and type tree := tree + + (** [empty _] is the empty tree. *) + val empty : t -> tree + + (** [is_empty t] is true iff [t] is [empty _]. *) + val is_empty : tree -> bool + + (** [kind t] is [t]'s kind. It's either a tree node or a leaf + value. *) + val kind : tree -> [`Value | `Tree] + + (** [to_value t] is [Some v] is [t] is a leaf tree and [None] otherwise. *) + val to_value : tree -> value option Lwt.t + + (** [hash t] is [t]'s Merkle hash. *) + val hash : tree -> Context_hash.t + + (** [equal x y] is true iff [x] and [y] have the same Merkle hash. *) + val equal : tree -> tree -> bool + + (** {2 Caches} *) + + (** [clear ?depth t] clears all caches in the tree [t] for subtrees with a + depth higher than [depth]. If [depth] is not set, all of the subtrees are + cleared. *) + val clear : ?depth:int -> tree -> unit +end + +module type T = sig + (** The type for root contexts. *) + type root + + include VIEW + + module Tree : + TREE + with type t := t + and type key := key + and type value := value + and type tree := tree + + (** Internally used in {!Storage_functors} to escape from a view. *) + val project : t -> root + + (** Internally used in {!Storage_functors} to retrieve a full key + from partial key relative a view. *) + val absolute_key : t -> key -> key + + (** Raised if block gas quota is exhausted during gas + consumption. *) + type error += Block_quota_exceeded + + (** Raised if operation gas quota is exhausted during gas + consumption. *) + type error += Operation_quota_exceeded + + (** Internally used in {!Storage_functors} to consume gas from + within a view. May raise {!Block_quota_exceeded} or + {!Operation_quota_exceeded}. *) + val consume_gas : t -> Gas_limit_repr.cost -> t tzresult + + (** Check if consume_gas will fail *) + val check_enough_gas : t -> Gas_limit_repr.cost -> unit tzresult + + val description : t Storage_description.t +end diff --git a/src/proto_009_PsFLoren/lib_protocol/raw_level_repr.ml b/src/proto_009_PsFLoren/lib_protocol/raw_level_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..c795ad5887048a404341bc55a6584b4557fa3115 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/raw_level_repr.ml @@ -0,0 +1,94 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = int32 + +type raw_level = t + +include (Compare.Int32 : Compare.S with type t := t) + +let encoding = Data_encoding.int32 + +let pp ppf level = Format.fprintf ppf "%ld" level + +let rpc_arg = + let construct raw_level = Int32.to_string raw_level in + let destruct str = + Int32.of_string_opt str |> Option.to_result ~none:"Cannot parse level" + in + RPC_arg.make + ~descr:"A level integer" + ~name:"block_level" + ~construct + ~destruct + () + +let root = 0l + +let succ = Int32.succ + +let pred l = if l = 0l then None else Some (Int32.pred l) + +let diff = Int32.sub + +let to_int32 l = l + +let of_int32_exn l = + if Compare.Int32.(l >= 0l) then l else invalid_arg "Level_repr.of_int32" + +type error += Unexpected_level of Int32.t (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"unexpected_level" + ~title:"Unexpected level" + ~description:"Level must be non-negative." + ~pp:(fun ppf l -> + Format.fprintf + ppf + "The level is %s but should be non-negative." + (Int32.to_string l)) + Data_encoding.(obj1 (req "level" int32)) + (function Unexpected_level l -> Some l | _ -> None) + (fun l -> Unexpected_level l) + +let of_int32 l = try Ok (of_int32_exn l) with _ -> error (Unexpected_level l) + +module Index = struct + type t = raw_level + + let path_length = 1 + + let to_path level l = Int32.to_string level :: l + + let of_path = function [s] -> Int32.of_string_opt s | _ -> None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_009_PsFLoren/lib_protocol/raw_level_repr.mli b/src/proto_009_PsFLoren/lib_protocol/raw_level_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..0f7dad593f867ceadac77d4a844d64e5674d40e4 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/raw_level_repr.mli @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The shell's notion of a level: an integer indicating the number of blocks + since genesis: genesis is 0, all other blocks have increasing levels from + there. *) +type t + +type raw_level = t + +val encoding : raw_level Data_encoding.t + +val rpc_arg : raw_level RPC_arg.arg + +val pp : Format.formatter -> raw_level -> unit + +include Compare.S with type t := raw_level + +val to_int32 : raw_level -> int32 + +val of_int32_exn : int32 -> raw_level + +val of_int32 : int32 -> raw_level tzresult + +val diff : raw_level -> raw_level -> int32 + +val root : raw_level + +val succ : raw_level -> raw_level + +val pred : raw_level -> raw_level option + +module Index : Storage_description.INDEX with type t = raw_level diff --git a/src/proto_009_PsFLoren/lib_protocol/receipt_repr.ml b/src/proto_009_PsFLoren/lib_protocol/receipt_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..13a7fd5072917f6dd03af7cc3634c992cb895634 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/receipt_repr.ml @@ -0,0 +1,146 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type balance = + | Contract of Contract_repr.t + | Rewards of Signature.Public_key_hash.t * Cycle_repr.t + | Fees of Signature.Public_key_hash.t * Cycle_repr.t + | Deposits of Signature.Public_key_hash.t * Cycle_repr.t + +let balance_encoding = + let open Data_encoding in + def "operation_metadata.alpha.balance" + @@ union + [ case + (Tag 0) + ~title:"Contract" + (obj2 + (req "kind" (constant "contract")) + (req "contract" Contract_repr.encoding)) + (function Contract c -> Some ((), c) | _ -> None) + (fun ((), c) -> Contract c); + case + (Tag 1) + ~title:"Rewards" + (obj4 + (req "kind" (constant "freezer")) + (req "category" (constant "rewards")) + (req "delegate" Signature.Public_key_hash.encoding) + (req "cycle" Cycle_repr.encoding)) + (function Rewards (d, l) -> Some ((), (), d, l) | _ -> None) + (fun ((), (), d, l) -> Rewards (d, l)); + case + (Tag 2) + ~title:"Fees" + (obj4 + (req "kind" (constant "freezer")) + (req "category" (constant "fees")) + (req "delegate" Signature.Public_key_hash.encoding) + (req "cycle" Cycle_repr.encoding)) + (function Fees (d, l) -> Some ((), (), d, l) | _ -> None) + (fun ((), (), d, l) -> Fees (d, l)); + case + (Tag 3) + ~title:"Deposits" + (obj4 + (req "kind" (constant "freezer")) + (req "category" (constant "deposits")) + (req "delegate" Signature.Public_key_hash.encoding) + (req "cycle" Cycle_repr.encoding)) + (function Deposits (d, l) -> Some ((), (), d, l) | _ -> None) + (fun ((), (), d, l) -> Deposits (d, l)) ] + +type balance_update = Debited of Tez_repr.t | Credited of Tez_repr.t + +let balance_update_encoding = + let open Data_encoding in + def "operation_metadata.alpha.balance_update" + @@ obj1 + (req + "change" + (conv + (function + | Credited v -> + Tez_repr.to_mutez v + | Debited v -> + Int64.neg (Tez_repr.to_mutez v)) + ( Json.wrap_error + @@ fun v -> + if Compare.Int64.(v < 0L) then + match Tez_repr.of_mutez (Int64.neg v) with + | Some v -> + Debited v + | None -> + failwith "Qty.of_mutez" + else + match Tez_repr.of_mutez v with + | Some v -> + Credited v + | None -> + failwith "Qty.of_mutez" ) + int64)) + +type update_origin = Block_application | Protocol_migration + +let update_origin_encoding = + let open Data_encoding in + def "operation_metadata.alpha.update_origin" + @@ obj1 @@ req "origin" + @@ union + [ case + (Tag 0) + ~title:"Block_application" + (constant "block") + (function Block_application -> Some () | _ -> None) + (fun () -> Block_application); + case + (Tag 1) + ~title:"Protocol_migration" + (constant "migration") + (function Protocol_migration -> Some () | _ -> None) + (fun () -> Protocol_migration) ] + +type balance_updates = (balance * balance_update * update_origin) list + +let balance_updates_encoding = + let open Data_encoding in + def "operation_metadata.alpha.balance_updates" + @@ list + (conv + (function + | (balance, balance_update, update_origin) -> + ((balance, balance_update), update_origin)) + (fun ((balance, balance_update), update_origin) -> + (balance, balance_update, update_origin)) + (merge_objs + (merge_objs balance_encoding balance_update_encoding) + update_origin_encoding)) + +let cleanup_balance_updates balance_updates = + List.filter + (fun (_, (Credited update | Debited update), _) -> + not (Tez_repr.equal update Tez_repr.zero)) + balance_updates diff --git a/src/proto_009_PsFLoren/lib_protocol/receipt_repr.mli b/src/proto_009_PsFLoren/lib_protocol/receipt_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..616e82225d2d6393936110769b3b6c415c3660be --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/receipt_repr.mli @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Places where tezzies can be found in the ledger's state. *) +type balance = + | Contract of Contract_repr.t + | Rewards of Signature.Public_key_hash.t * Cycle_repr.t + | Fees of Signature.Public_key_hash.t * Cycle_repr.t + | Deposits of Signature.Public_key_hash.t * Cycle_repr.t + +(** A credit or debit of tezzies to a balance. *) +type balance_update = Debited of Tez_repr.t | Credited of Tez_repr.t + +(** An origin of a balance update *) +type update_origin = + | Block_application (** Update from a block application *) + | Protocol_migration (** Update from a protocol migration *) + +(** A list of balance updates. Duplicates may happen. *) +type balance_updates = (balance * balance_update * update_origin) list + +val balance_updates_encoding : balance_updates Data_encoding.t + +(** Remove zero-valued balances from a list of updates. *) +val cleanup_balance_updates : balance_updates -> balance_updates diff --git a/src/proto_009_PsFLoren/lib_protocol/roll_repr.ml b/src/proto_009_PsFLoren/lib_protocol/roll_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..74b47360b2ace54d0ad6efac2f2fdcd620a3ba57 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/roll_repr.ml @@ -0,0 +1,65 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Compare.Int32 + +type roll = t + +let encoding = Data_encoding.int32 + +let first = 0l + +let succ i = Int32.succ i + +let random sequence ~bound = Seed_repr.take_int32 sequence bound + +let rpc_arg = RPC_arg.like RPC_arg.int32 "roll" + +let to_int32 v = v + +module Index = struct + type t = roll + + let path_length = 3 + + let to_path roll l = + (Int32.to_string @@ Int32.logand roll (Int32.of_int 0xff)) + :: ( Int32.to_string + @@ Int32.logand (Int32.shift_right_logical roll 8) (Int32.of_int 0xff) + ) + :: Int32.to_string roll :: l + + let of_path = function + | _ :: _ :: s :: _ -> + Int32.of_string_opt s + | _ -> + None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_009_PsFLoren/lib_protocol/roll_repr.mli b/src/proto_009_PsFLoren/lib_protocol/roll_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..cb792b0128e73203abec091ee1aadf019aa356a1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/roll_repr.mli @@ -0,0 +1,44 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = private int32 + +type roll = t + +val encoding : roll Data_encoding.t + +val rpc_arg : roll RPC_arg.t + +val random : Seed_repr.sequence -> bound:roll -> roll * Seed_repr.sequence + +val first : roll + +val succ : roll -> roll + +val to_int32 : roll -> Int32.t + +val ( = ) : roll -> roll -> bool + +module Index : Storage_description.INDEX with type t = roll diff --git a/src/proto_009_PsFLoren/lib_protocol/roll_storage.ml b/src/proto_009_PsFLoren/lib_protocol/roll_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..42fb65627a50a62bff13ff5698ed69fbcb6eed92 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/roll_storage.ml @@ -0,0 +1,578 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Misc + +type error += + | (* `Permanent *) Consume_roll_change + | (* `Permanent *) No_roll_for_delegate + | (* `Permanent *) No_roll_snapshot_for_cycle of Cycle_repr.t + | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t + +let () = + let open Data_encoding in + (* Consume roll change *) + register_error_kind + `Permanent + ~id:"contract.manager.consume_roll_change" + ~title:"Consume roll change" + ~description:"Change is not enough to consume a roll." + ~pp:(fun ppf () -> + Format.fprintf ppf "Not enough change to consume a roll.") + empty + (function Consume_roll_change -> Some () | _ -> None) + (fun () -> Consume_roll_change) ; + (* No roll for delegate *) + register_error_kind + `Permanent + ~id:"contract.manager.no_roll_for_delegate" + ~title:"No roll for delegate" + ~description:"Delegate has no roll." + ~pp:(fun ppf () -> Format.fprintf ppf "Delegate has no roll.") + empty + (function No_roll_for_delegate -> Some () | _ -> None) + (fun () -> No_roll_for_delegate) ; + (* No roll snapshot for cycle *) + register_error_kind + `Permanent + ~id:"contract.manager.no_roll_snapshot_for_cycle" + ~title:"No roll snapshot for cycle" + ~description: + "A snapshot of the rolls distribution does not exist for this cycle." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "A snapshot of the rolls distribution does not exist for cycle %a" + Cycle_repr.pp + c) + (obj1 (req "cycle" Cycle_repr.encoding)) + (function No_roll_snapshot_for_cycle c -> Some c | _ -> None) + (fun c -> No_roll_snapshot_for_cycle c) ; + (* Unregistered delegate *) + register_error_kind + `Permanent + ~id:"contract.manager.unregistered_delegate" + ~title:"Unregistered delegate" + ~description:"A contract cannot be delegated to an unregistered delegate" + ~pp:(fun ppf k -> + Format.fprintf + ppf + "The provided public key (with hash %a) is not registered as valid \ + delegate key." + Signature.Public_key_hash.pp + k) + (obj1 (req "hash" Signature.Public_key_hash.encoding)) + (function Unregistered_delegate k -> Some k | _ -> None) + (fun k -> Unregistered_delegate k) + +let get_contract_delegate ctxt contract = + Storage.Contract.Delegate.find ctxt contract + +let delegate_pubkey ctxt delegate = + Storage.Contract.Manager.find ctxt (Contract_repr.implicit_contract delegate) + >>=? function + | None | Some (Manager_repr.Hash _) -> + fail (Unregistered_delegate delegate) + | Some (Manager_repr.Public_key pk) -> + return pk + +let clear_cycle ctxt cycle = + Storage.Roll.Snapshot_for_cycle.get ctxt cycle + >>=? fun index -> + Storage.Roll.Snapshot_for_cycle.remove_existing ctxt cycle + >>=? fun ctxt -> + Storage.Roll.Last_for_snapshot.remove_existing (ctxt, cycle) index + >>=? fun ctxt -> + Storage.Roll.Owner.delete_snapshot ctxt (cycle, index) >|= ok + +let fold ctxt ~f init = + Storage.Roll.Next.get ctxt + >>=? fun last -> + let rec loop ctxt roll acc = + if Roll_repr.(roll = last) then return acc + else + Storage.Roll.Owner.find ctxt roll + >>=? function + | None -> + loop ctxt (Roll_repr.succ roll) acc + | Some delegate -> + f roll delegate acc + >>=? fun acc -> loop ctxt (Roll_repr.succ roll) acc + in + loop ctxt Roll_repr.first init + +let snapshot_rolls_for_cycle ctxt cycle = + Storage.Roll.Snapshot_for_cycle.get ctxt cycle + >>=? fun index -> + Storage.Roll.Snapshot_for_cycle.update ctxt cycle (index + 1) + >>=? fun ctxt -> + Storage.Roll.Owner.snapshot ctxt (cycle, index) + >>=? fun ctxt -> + Storage.Roll.Next.get ctxt + >>=? fun last -> Storage.Roll.Last_for_snapshot.init (ctxt, cycle) index last + +(* NOTE: Deletes all snapshots for a given cycle that are not randomly selected. *) +let freeze_rolls_for_cycle ctxt cycle = + Storage.Roll.Snapshot_for_cycle.get ctxt cycle + >>=? fun max_index -> + Storage.Seed.For_cycle.get ctxt cycle + >>=? fun seed -> + let rd = Seed_repr.initialize_new seed [Bytes.of_string "roll_snapshot"] in + let seq = Seed_repr.sequence rd 0l in + let selected_index = + Seed_repr.take_int32 seq (Int32.of_int max_index) |> fst |> Int32.to_int + in + Storage.Roll.Snapshot_for_cycle.update ctxt cycle selected_index + >>=? fun ctxt -> + fold_left_s + (fun ctxt index -> + if Compare.Int.(index = selected_index) then return ctxt + else + Storage.Roll.Owner.delete_snapshot ctxt (cycle, index) + >>= fun ctxt -> + Storage.Roll.Last_for_snapshot.remove_existing (ctxt, cycle) index) + ctxt + Misc.(0 --> (max_index - 1)) + +(* Roll selection *) +module Random = struct + let int32_to_bytes i = + let b = Bytes.make 4 '0' in + TzEndian.set_int32 b 0 i ; b + + let level_random seed use (level : Level_repr.t) = + let position = level.Level_repr.cycle_position in + Seed_repr.initialize_new + seed + [Bytes.of_string ("level " ^ use ^ ":"); int32_to_bytes position] + + let owner c kind (level : Level_repr.t) offset = + let cycle = level.Level_repr.cycle in + Seed_storage.for_cycle c cycle + >>=? fun random_seed -> + let rd = level_random random_seed kind level in + let sequence = Seed_repr.sequence rd (Int32.of_int offset) in + Storage.Roll.Snapshot_for_cycle.get c cycle + >>=? fun index -> + Storage.Roll.Last_for_snapshot.get (c, cycle) index + >>=? fun bound -> + let rec loop sequence = + let (roll, sequence) = Roll_repr.random sequence ~bound in + Storage.Roll.Owner.Snapshot.find c ((cycle, index), roll) + >>=? function None -> loop sequence | Some delegate -> return delegate + in + Storage.Roll.Owner.snapshot_exists c (cycle, index) + >>= fun snapshot_exists -> + error_unless snapshot_exists (No_roll_snapshot_for_cycle cycle) + >>?= fun () -> loop sequence +end + +let baking_rights_owner c level ~priority = + Random.owner c "baking" level priority + +let endorsement_rights_owner c level ~slot = + Random.owner c "endorsement" level slot + +let count_rolls ctxt delegate = + Storage.Roll.Delegate_roll_list.find ctxt delegate + >>=? function + | None -> + return 0 + | Some head_roll -> + let rec loop acc roll = + Storage.Roll.Successor.find ctxt roll + >>=? function None -> return acc | Some next -> loop (succ acc) next + in + loop 1 head_roll + +let get_change ctxt delegate = + Storage.Roll.Delegate_change.find ctxt delegate + >|=? Option.value ~default:Tez_repr.zero + +module Delegate = struct + let fresh_roll ctxt = + Storage.Roll.Next.get ctxt + >>=? fun roll -> + Storage.Roll.Next.update ctxt (Roll_repr.succ roll) + >|=? fun ctxt -> (roll, ctxt) + + let get_limbo_roll ctxt = + Storage.Roll.Limbo.find ctxt + >>=? function + | None -> + fresh_roll ctxt + >>=? fun (roll, ctxt) -> + Storage.Roll.Limbo.init ctxt roll >|=? fun ctxt -> (roll, ctxt) + | Some roll -> + return (roll, ctxt) + + let consume_roll_change ctxt delegate = + let tokens_per_roll = Constants_storage.tokens_per_roll ctxt in + Storage.Roll.Delegate_change.get ctxt delegate + >>=? fun change -> + record_trace Consume_roll_change Tez_repr.(change -? tokens_per_roll) + >>?= fun new_change -> + Storage.Roll.Delegate_change.update ctxt delegate new_change + + let recover_roll_change ctxt delegate = + let tokens_per_roll = Constants_storage.tokens_per_roll ctxt in + Storage.Roll.Delegate_change.get ctxt delegate + >>=? fun change -> + Tez_repr.(change +? tokens_per_roll) + >>?= fun new_change -> + Storage.Roll.Delegate_change.update ctxt delegate new_change + + let pop_roll_from_delegate ctxt delegate = + recover_roll_change ctxt delegate + >>=? fun ctxt -> + (* beginning: + delegate : roll -> successor_roll -> ... + limbo : limbo_head -> ... + *) + Storage.Roll.Limbo.find ctxt + >>=? fun limbo_head -> + Storage.Roll.Delegate_roll_list.find ctxt delegate + >>=? function + | None -> + fail No_roll_for_delegate + | Some roll -> + Storage.Roll.Owner.remove_existing ctxt roll + >>=? fun ctxt -> + Storage.Roll.Successor.find ctxt roll + >>=? fun successor_roll -> + Storage.Roll.Delegate_roll_list.add_or_remove + ctxt + delegate + successor_roll + >>= fun ctxt -> + (* delegate : successor_roll -> ... + roll ------^ + limbo : limbo_head -> ... *) + Storage.Roll.Successor.add_or_remove ctxt roll limbo_head + >>= fun ctxt -> + (* delegate : successor_roll -> ... + roll ------v + limbo : limbo_head -> ... *) + Storage.Roll.Limbo.add ctxt roll + >|= fun ctxt -> + (* delegate : successor_roll -> ... + limbo : roll -> limbo_head -> ... *) + ok (roll, ctxt) + + let create_roll_in_delegate ctxt delegate delegate_pk = + consume_roll_change ctxt delegate + >>=? fun ctxt -> + (* beginning: + delegate : delegate_head -> ... + limbo : roll -> limbo_successor -> ... + *) + Storage.Roll.Delegate_roll_list.find ctxt delegate + >>=? fun delegate_head -> + get_limbo_roll ctxt + >>=? fun (roll, ctxt) -> + Storage.Roll.Owner.init ctxt roll delegate_pk + >>=? fun ctxt -> + Storage.Roll.Successor.find ctxt roll + >>=? fun limbo_successor -> + Storage.Roll.Limbo.add_or_remove ctxt limbo_successor + >>= fun ctxt -> + (* delegate : delegate_head -> ... + roll ------v + limbo : limbo_successor -> ... *) + Storage.Roll.Successor.add_or_remove ctxt roll delegate_head + >>= fun ctxt -> + (* delegate : delegate_head -> ... + roll ------^ + limbo : limbo_successor -> ... *) + Storage.Roll.Delegate_roll_list.add ctxt delegate roll + (* delegate : roll -> delegate_head -> ... + limbo : limbo_successor -> ... *) + >|= ok + + let ensure_inited ctxt delegate = + Storage.Roll.Delegate_change.mem ctxt delegate + >>= function + | true -> + return ctxt + | false -> + Storage.Roll.Delegate_change.init ctxt delegate Tez_repr.zero + + let is_inactive ctxt delegate = + Storage.Contract.Inactive_delegate.mem + ctxt + (Contract_repr.implicit_contract delegate) + >>= fun inactive -> + if inactive then return inactive + else + Storage.Contract.Delegate_desactivation.find + ctxt + (Contract_repr.implicit_contract delegate) + >|=? function + | Some last_active_cycle -> + let ({Level_repr.cycle = current_cycle} : Level_repr.t) = + Raw_context.current_level ctxt + in + Cycle_repr.(last_active_cycle < current_cycle) + | None -> + (* This case is only when called from `set_active`, when creating + a contract. *) + false + + let add_amount ctxt delegate amount = + ensure_inited ctxt delegate + >>=? fun ctxt -> + let tokens_per_roll = Constants_storage.tokens_per_roll ctxt in + Storage.Roll.Delegate_change.get ctxt delegate + >>=? fun change -> + Tez_repr.(amount +? change) + >>?= fun change -> + Storage.Roll.Delegate_change.update ctxt delegate change + >>=? fun ctxt -> + delegate_pubkey ctxt delegate + >>=? fun delegate_pk -> + let rec loop ctxt change = + if Tez_repr.(change < tokens_per_roll) then return ctxt + else + Tez_repr.(change -? tokens_per_roll) + >>?= fun change -> + create_roll_in_delegate ctxt delegate delegate_pk + >>=? fun ctxt -> loop ctxt change + in + is_inactive ctxt delegate + >>=? fun inactive -> + if inactive then return ctxt + else + loop ctxt change + >>=? fun ctxt -> + Storage.Roll.Delegate_roll_list.find ctxt delegate + >>=? fun rolls -> + match rolls with + | None -> + return ctxt + | Some _ -> + Storage.Active_delegates_with_rolls.add ctxt delegate >|= ok + + let remove_amount ctxt delegate amount = + let tokens_per_roll = Constants_storage.tokens_per_roll ctxt in + let rec loop ctxt change = + if Tez_repr.(amount <= change) then return (ctxt, change) + else + pop_roll_from_delegate ctxt delegate + >>=? fun (_, ctxt) -> + Tez_repr.(change +? tokens_per_roll) + >>?= fun change -> loop ctxt change + in + Storage.Roll.Delegate_change.get ctxt delegate + >>=? fun change -> + is_inactive ctxt delegate + >>=? fun inactive -> + ( if inactive then return (ctxt, change) + else + loop ctxt change + >>=? fun (ctxt, change) -> + Storage.Roll.Delegate_roll_list.find ctxt delegate + >>=? fun rolls -> + match rolls with + | None -> + Storage.Active_delegates_with_rolls.remove ctxt delegate + >|= fun ctxt -> ok (ctxt, change) + | Some _ -> + return (ctxt, change) ) + >>=? fun (ctxt, change) -> + Tez_repr.(change -? amount) + >>?= fun change -> Storage.Roll.Delegate_change.update ctxt delegate change + + let set_inactive ctxt delegate = + ensure_inited ctxt delegate + >>=? fun ctxt -> + let tokens_per_roll = Constants_storage.tokens_per_roll ctxt in + Storage.Roll.Delegate_change.get ctxt delegate + >>=? fun change -> + Storage.Contract.Inactive_delegate.add + ctxt + (Contract_repr.implicit_contract delegate) + >>= fun ctxt -> + Storage.Active_delegates_with_rolls.remove ctxt delegate + >>= fun ctxt -> + let rec loop ctxt change = + Storage.Roll.Delegate_roll_list.find ctxt delegate + >>=? function + | None -> + return (ctxt, change) + | Some _roll -> + pop_roll_from_delegate ctxt delegate + >>=? fun (_, ctxt) -> + Tez_repr.(change +? tokens_per_roll) + >>?= fun change -> loop ctxt change + in + loop ctxt change + >>=? fun (ctxt, change) -> + Storage.Roll.Delegate_change.update ctxt delegate change + + let set_active ctxt delegate = + is_inactive ctxt delegate + >>=? fun inactive -> + let current_cycle = (Raw_context.current_level ctxt).cycle in + let preserved_cycles = Constants_storage.preserved_cycles ctxt in + (* When the delegate is new or inactive, she will become active in + `1+preserved_cycles`, and we allow `preserved_cycles` for the + delegate to start baking. When the delegate is active, we only + give her at least `preserved_cycles` after the current cycle + before to be deactivated. *) + Storage.Contract.Delegate_desactivation.find + ctxt + (Contract_repr.implicit_contract delegate) + >>=? fun current_expiration -> + let expiration = + match current_expiration with + | None -> + Cycle_repr.add current_cycle (1 + (2 * preserved_cycles)) + | Some current_expiration -> + let delay = + if inactive then 1 + (2 * preserved_cycles) + else 1 + preserved_cycles + in + let updated = Cycle_repr.add current_cycle delay in + Cycle_repr.max current_expiration updated + in + Storage.Contract.Delegate_desactivation.add + ctxt + (Contract_repr.implicit_contract delegate) + expiration + >>= fun ctxt -> + if not inactive then return ctxt + else + ensure_inited ctxt delegate + >>=? fun ctxt -> + let tokens_per_roll = Constants_storage.tokens_per_roll ctxt in + Storage.Roll.Delegate_change.get ctxt delegate + >>=? fun change -> + Storage.Contract.Inactive_delegate.remove + ctxt + (Contract_repr.implicit_contract delegate) + >>= fun ctxt -> + delegate_pubkey ctxt delegate + >>=? fun delegate_pk -> + let rec loop ctxt change = + if Tez_repr.(change < tokens_per_roll) then return ctxt + else + Tez_repr.(change -? tokens_per_roll) + >>?= fun change -> + create_roll_in_delegate ctxt delegate delegate_pk + >>=? fun ctxt -> loop ctxt change + in + loop ctxt change + >>=? fun ctxt -> + Storage.Roll.Delegate_roll_list.find ctxt delegate + >>=? fun rolls -> + match rolls with + | None -> + return ctxt + | Some _ -> + Storage.Active_delegates_with_rolls.add ctxt delegate >|= ok +end + +module Contract = struct + let add_amount c contract amount = + get_contract_delegate c contract + >>=? function + | None -> return c | Some delegate -> Delegate.add_amount c delegate amount + + let remove_amount c contract amount = + get_contract_delegate c contract + >>=? function + | None -> + return c + | Some delegate -> + Delegate.remove_amount c delegate amount +end + +let init ctxt = Storage.Roll.Next.init ctxt Roll_repr.first + +let init_first_cycles ctxt = + let preserved = Constants_storage.preserved_cycles ctxt in + (* Precompute rolls for cycle (0 --> preserved_cycles) *) + fold_left_s + (fun ctxt c -> + let cycle = Cycle_repr.of_int32_exn (Int32.of_int c) in + Storage.Roll.Snapshot_for_cycle.init ctxt cycle 0 + >>=? fun ctxt -> + snapshot_rolls_for_cycle ctxt cycle + >>=? fun ctxt -> freeze_rolls_for_cycle ctxt cycle) + ctxt + (0 --> preserved) + >>=? fun ctxt -> + let cycle = Cycle_repr.of_int32_exn (Int32.of_int (preserved + 1)) in + (* Precomputed a snapshot for cycle (preserved_cycles + 1) *) + Storage.Roll.Snapshot_for_cycle.init ctxt cycle 0 + >>=? fun ctxt -> + snapshot_rolls_for_cycle ctxt cycle + >>=? fun ctxt -> + (* Prepare storage for storing snapshots for cycle (preserved_cycles+2) *) + let cycle = Cycle_repr.of_int32_exn (Int32.of_int (preserved + 2)) in + Storage.Roll.Snapshot_for_cycle.init ctxt cycle 0 + +let snapshot_rolls ctxt = + let current_level = Raw_context.current_level ctxt in + let preserved = Constants_storage.preserved_cycles ctxt in + let cycle = Cycle_repr.add current_level.cycle (preserved + 2) in + snapshot_rolls_for_cycle ctxt cycle + +let cycle_end ctxt last_cycle = + let preserved = Constants_storage.preserved_cycles ctxt in + ( match Cycle_repr.sub last_cycle preserved with + | None -> + return ctxt + | Some cleared_cycle -> + clear_cycle ctxt cleared_cycle ) + >>=? fun ctxt -> + let frozen_roll_cycle = Cycle_repr.add last_cycle (preserved + 1) in + freeze_rolls_for_cycle ctxt frozen_roll_cycle + >>=? fun ctxt -> + Storage.Roll.Snapshot_for_cycle.init + ctxt + (Cycle_repr.succ (Cycle_repr.succ frozen_roll_cycle)) + 0 + +let update_tokens_per_roll ctxt new_tokens_per_roll = + let constants = Raw_context.constants ctxt in + let old_tokens_per_roll = constants.tokens_per_roll in + Raw_context.patch_constants ctxt (fun constants -> + {constants with Constants_repr.tokens_per_roll = new_tokens_per_roll}) + >>= fun ctxt -> + let decrease = Tez_repr.(new_tokens_per_roll < old_tokens_per_roll) in + ( if decrease then Tez_repr.(old_tokens_per_roll -? new_tokens_per_roll) + else Tez_repr.(new_tokens_per_roll -? old_tokens_per_roll) ) + >>?= fun abs_diff -> + Storage.Delegates.fold ctxt (Ok ctxt) (fun pkh ctxt_opt -> + ctxt_opt + >>?= fun ctxt -> + count_rolls ctxt pkh + >>=? fun rolls -> + Tez_repr.(abs_diff *? Int64.of_int rolls) + >>?= fun amount -> + if decrease then Delegate.add_amount ctxt pkh amount + else Delegate.remove_amount ctxt pkh amount) diff --git a/src/proto_009_PsFLoren/lib_protocol/roll_storage.mli b/src/proto_009_PsFLoren/lib_protocol/roll_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..e88cbefe97880573541b9445fff144483a9f11c9 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/roll_storage.mli @@ -0,0 +1,264 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** + Basic roll manipulation. + + The storage related to roll (i.e. `Storage.Roll`) is not used outside of + this module. And, this interface enforces the invariant that a roll is + always either in the limbo list or owned by a delegate. +*) + +type error += + | (* `Permanent *) Consume_roll_change + | (* `Permanent *) No_roll_for_delegate + | (* `Permanent *) No_roll_snapshot_for_cycle of Cycle_repr.t + | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t + +(** + [init ctxt] returns a new context initialized from [ctxt] where the next + roll to be allocated is the first roll, i.e. + [(Storage.Roll.Next.get ctxt) = Roll_repr.first]. + This function returns a [{!Storage_error Existing_key}] error if the context + has already been initialized. +*) +val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** + [init_first_cycles ctxt] computes a new context from [ctxt] where the store + has been prepared to save roll snapshots for all cycles from [0] to + [Constants.preserved_cycles + 2]: + + 1. rolls for all cycles in the interval [(0, preserved_cycles)] are frozen + (after taking a snapshot), + 2. a snapshot is taken for rolls of cycle [preserved_cycles + 1], + 3. rolls for cycle [preserved_cycles + 2] are ready for a snapshot, i.e. the + necessary storage has been prepared. +*) +val init_first_cycles : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** + [cycle_end ctxt last_cycle] returns a new context after applying the + end-of-cycle bookkeeping to [ctxt]: + + 1. clears cycle [c = (last_cycle - preserved_cycles)] if [last_cycle >= + preserved_cycles] (this amounts to deleting the only snapshot left after + the freezing of [c]), + 2. freezes snapshot rolls for the cycle + [(last_cycle + preserved_cycles + 1)] (this amounts to removing all + snapshots for the cycle, except one randomly selected for computing + baking rights), + 3. makes cycle [(last_cycle + preserved_cycles + 2)] ready for snapshot. +*) +val cycle_end : Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +(** + [snapshot_rolls ctxt] creates roll snapshots for cycle + [c = level + preserved_cycles + 2]. The returned context is such that: + + 1. the snapshot index associated to cycle [c] is incremented, + 2. the rolls' owners are copied and associated to the snapshot id + [(c,index)] (where [index] is the current snapshot index of cycle [c]), + 3. the last roll for cycle [c], and snapshot [index] is set to be the next + roll of [ctxt]. +*) +val snapshot_rolls : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** + [fold ctxt f init] folds [f] on the list of all rolls from [Roll_repr.first] + to [Storage.Next.Roll] of the context [ctxt]. Only rolls which have owners + are considered, rolls without owners are skipped. The first parameter of [f] + is a roll [r], the second parameter of [f] is the owner of [r], and the last + parameter is the initial value of the accumulator. +*) +val fold : + Raw_context.t -> + f:(Roll_repr.roll -> Signature.Public_key.t -> 'a -> 'a tzresult Lwt.t) -> + 'a -> + 'a tzresult Lwt.t + +(** + May return a [No_roll_snapshot_for_cycle] error. +*) +val baking_rights_owner : + Raw_context.t -> + Level_repr.t -> + priority:int -> + Signature.Public_key.t tzresult Lwt.t + +(** + May return a [No_roll_snapshot_for_cycle] error. +*) +val endorsement_rights_owner : + Raw_context.t -> + Level_repr.t -> + slot:int -> + Signature.Public_key.t tzresult Lwt.t + +module Delegate : sig + val is_inactive : + Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + + (** + [add_amount ctxt dlg am] performs the following actions: + + 1. if the delegate [dlg] is inactive, increase its change [chg] by [am], + 2. if the [dlg] is active, update [dlg]'s number of rolls [nr], and change + [chg] so that [dlg]'s number of tokens is increased by [am], and equal + to [nr * tokens_per_roll + chg], where [chg < tokens_per_roll]. + *) + val add_amount : + Raw_context.t -> + Signature.Public_key_hash.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + + (** + [remove_amount ctxt dlg am] performs the following actions: + + 1. if the delegate [dlg] is inactive, decrease its change [chg] by [am], + 2. if the [dlg] is active, update [dlg]'s number of rolls [nr], and change + [chg] so that [dlg]'s number of tokens is decreased by [am], and equal to + [nr * tokens_per_roll + chg], where [chg < tokens_per_roll]. + *) + val remove_amount : + Raw_context.t -> + Signature.Public_key_hash.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + + (** + [set_inactive ctxt dlg] renders delegate [dlg] inactive and performs the + following actions: + + 1. empty the list of rolls of [dlg], + 2. increase the change of [dlg] by [nr * tokens_per_roll], where [nr] is + [dlg]'s number of rolls prior to inactivation. + *) + val set_inactive : + Raw_context.t -> + Signature.Public_key_hash.t -> + Raw_context.t tzresult Lwt.t + + (** + If the delegate [dlg] is already active then [set_active ctxt dlg] + performs the following sequence of actions: + + 1. if the delegate is not scheduled to become inactive, then schedule the + delegate to become inactive after [(preserved_cycles * 2) + 1] cycles, + 2. if the delegate is already scheduled to become inactive at cycle [ic], + then re-schedule it to become inactive at cycle + [max ic (cc + preserved_cycles + 1)], where [cc] is the current cycle. + + If [dlg] is inactive then this function puts [dlg] in active state and + performs the following actions: + + 1. if [dlg] is not scheduled to become inactive, schedule [dlg] to become + inactive after [(preserved_cycles * 2) + 1] cycles, + 2. if the [dlg] is already scheduled to become inactive at cycle [ic], + then re-schedule it to become inactive at cycle + [max ic (cc + (preserved_cycles * 2) + 1)], where [cc] is the current + cycle, + 3. dispatch [dlg]'s change [chg] into [nr] rolls of size [tokens_per_roll] + so that the total amount managed by [dlg] is unchanged and equal to + [(nr * tokens_per_roll) + chg], where [chg < tokens_per_roll]. + *) + val set_active : + Raw_context.t -> + Signature.Public_key_hash.t -> + Raw_context.t tzresult Lwt.t +end + +module Contract : sig + (** + Calls [Delegate.add_amount ctxt contract am] if a delegate is associated + to [contract], or returns unchanged [ctxt] otherwise. + *) + val add_amount : + Raw_context.t -> + Contract_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + + (** + Calls [Delegate.remove_amount ctxt contract am] if a delegate is associated + to [contract], or returns unchanged [ctxt] otherwise. + *) + val remove_amount : + Raw_context.t -> + Contract_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t +end + +(** + [delegate_pubkey ctxt delegate] returns the public key of + [delegate] found in context [ctxt] if there exists a registered + contract. +*) +val delegate_pubkey : + Raw_context.t -> + Signature.Public_key_hash.t -> + Signature.Public_key.t tzresult Lwt.t + +(** + [count_rolls ctxt delegate] returns the number of rolls held by + [delegate] in context [ctxt]. +*) +val count_rolls : + Raw_context.t -> Signature.Public_key_hash.t -> int tzresult Lwt.t + +(** + [get_change ctxt delegate] returns the amount of change held by + [delegate] in context [ctxt]. The change is the part of the staking + balance of a delegate that is not part of a roll, i.e., the amount + of staking balance (smaller than the value of a roll) not being + taken into account for baking rights computation. +*) +val get_change : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + +(** + [update_tokens_per_roll ctxt am] performs the following actions: + + 1. set the constant [tokens_per_roll] to [am], + 2. if the constant was increased by [tpram], then add the amount + [nr * tpram] to each delegate, where [nr] is the delegate's + number of rolls, + 3. if the constant was instead decreased by [tpram], then remove + the amount [nr * tpram] from all delegates. +*) +val update_tokens_per_roll : + Raw_context.t -> Tez_repr.t -> Raw_context.t tzresult Lwt.t + +(** + [get_contract_delegate ctxt contract] returns the public key hash + of the delegate whose contract is [contract] in context [ctxt]. +*) +val get_contract_delegate : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t option tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/sapling_repr.ml b/src/proto_009_PsFLoren/lib_protocol/sapling_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..8ae12914e66effda5240a005c64f0e101d395f4e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/sapling_repr.ml @@ -0,0 +1,95 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +type transaction = Sapling.UTXO.transaction + +let transaction_encoding = Sapling.UTXO.transaction_encoding + +(* The two data structures in the state are all ordered by position, a diff + contains the elements starting from an offset position up to the most recent + position. A diff can be applied to a state stored in a context to obtain a + new state. + Diffs are used by the Michelson interpreter during the evaluation of smart + contracts to keep a temporary state that may be discarded. + Diffs are also returned by an RPC to allow a client to synchronize its own + state with the chain. + *) +type diff = { + commitments_and_ciphertexts : + (Sapling.Commitment.t * Sapling.Ciphertext.t) list; + nullifiers : Sapling.Nullifier.t list; +} + +let diff_encoding = + let open Data_encoding in + conv + (fun d -> (d.commitments_and_ciphertexts, d.nullifiers)) + (fun (commitments_and_ciphertexts, nullifiers) -> + ( match commitments_and_ciphertexts with + | [] -> + () + | (_cm_hd, ct_hd) :: rest -> + let memo_size = Sapling.Ciphertext.get_memo_size ct_hd in + List.iter + (fun (_cm, ct) -> + assert ( + Compare.Int.(Sapling.Ciphertext.get_memo_size ct = memo_size) + )) + rest ) ; + {commitments_and_ciphertexts; nullifiers}) + (obj2 + (req + "commitments_and_ciphertexts" + (list (tup2 Sapling.Commitment.encoding Sapling.Ciphertext.encoding))) + (req "nullifiers" (list Sapling.Nullifier.encoding))) + +module Memo_size = struct + type t = int + + let encoding = Data_encoding.uint16 + + let equal = Compare.Int.( = ) + + let max_uint16 = 0xffff + + let max_uint16_z = Z.of_int max_uint16 + + let err = + Error + ( "a positive 16-bit integer (between 0 and " ^ string_of_int max_uint16 + ^ ")" ) + + let parse_z z = + if Compare.Z.(Z.zero <= z) && Compare.Z.(z <= max_uint16_z) then + Ok (Z.to_int z) + else err + + let unparse_to_z = Z.of_int +end + +let transaction_get_memo_size (transaction : Sapling.UTXO.transaction) = + match transaction.outputs with + | [] -> + None + | {ciphertext; _} :: _ -> + (* Encoding ensures all ciphertexts have the same memo size. *) + Some (Sapling.Ciphertext.get_memo_size ciphertext) diff --git a/src/proto_009_PsFLoren/lib_protocol/sapling_services.ml b/src/proto_009_PsFLoren/lib_protocol/sapling_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..dc5675c97e19fbd2d3b90bb5980f77b403cec87e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/sapling_services.ml @@ -0,0 +1,100 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +open Alpha_context + +let custom_root = + ( RPC_path.(open_root / "context" / "sapling") + : RPC_context.t RPC_path.context ) + +type diff_query = { + offset_commitment : Int64.t option; + offset_nullifier : Int64.t option; +} + +module S = struct + module Args = struct + type ('query, 'output) t = { + name : string; + description : string; + query : 'query RPC_query.t; + output : 'output Data_encoding.t; + f : context -> Sapling.Id.t -> 'query -> 'output tzresult Lwt.t; + } + + let get_diff_query : diff_query RPC_query.t = + let open RPC_query in + query (fun offset_commitment offset_nullifier -> + {offset_commitment; offset_nullifier}) + |+ opt_field + ~descr: + "Commitments and ciphertexts are returned from the specified \ + offset up to the most recent." + "offset_commitment" + RPC_arg.int64 + (fun {offset_commitment; _} -> offset_commitment) + |+ opt_field + ~descr: + "Nullifiers are returned from the specified offset up to the \ + most recent." + "offset_nullifier" + RPC_arg.int64 + (fun {offset_nullifier; _} -> offset_nullifier) + |> seal + + let encoding = + let open Data_encoding in + merge_objs + (obj1 (req "root" Sapling.root_encoding)) + Sapling.diff_encoding + + let get_diff = + { + name = "get_diff"; + description = + "Returns the root and a diff of a state starting from an optional \ + offset which is zero by default."; + query = get_diff_query; + output = encoding; + f = + (fun ctxt id {offset_commitment; offset_nullifier} -> + Sapling.get_diff ctxt id ?offset_commitment ?offset_nullifier ()); + } + end + + let make_service Args.{name; description; query; output; f} = + let path = RPC_path.(custom_root /: Sapling.rpc_arg / name) in + let service = RPC_service.get_service ~description ~query ~output path in + (service, fun ctxt id q () -> f ctxt id q) + + let get_diff = make_service Args.get_diff +end + +let register () = + let reg (service, f) = Services_registration.register1 service f in + reg S.get_diff + +let mk_call1 (service, _f) ctxt block id q = + RPC_context.make_call1 service ctxt block id q () + +let get_diff ctxt block id ?offset_commitment ?offset_nullifier () = + mk_call1 S.get_diff ctxt block id {offset_commitment; offset_nullifier} diff --git a/src/proto_009_PsFLoren/lib_protocol/sapling_storage.ml b/src/proto_009_PsFLoren/lib_protocol/sapling_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..8e2e57aff3509e1a1dc9700f2bc207a72d908406 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/sapling_storage.ml @@ -0,0 +1,515 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +module Commitments : sig + val init : Raw_context.t -> Storage.Sapling.id -> Raw_context.t Lwt.t + + val default_root : Sapling.Hash.t + + val get_root : + Raw_context.t -> + Storage.Sapling.id -> + (Raw_context.t * Sapling.Hash.t) tzresult Lwt.t + + val add : + Raw_context.t -> + Storage.Sapling.id -> + Sapling.Commitment.t list -> + int64 -> + (Raw_context.t * int) tzresult Lwt.t + + val get_from : + Raw_context.t -> + Storage.Sapling.id -> + int64 -> + Sapling.Commitment.t list tzresult Lwt.t +end = struct + module H = Sapling.Hash + + (** Incremental Merkle Tree + * + * A tree of height h contains 2^h leaves and h+1 levels of nodes with + * leaves at level 0 and root at level h. + * + * The leaves are commitments and the tree it is treated as always filled + * with a default value H.uncommitted. This allows to have proofs of + * membership, or witnesses, of fixed size. + * + * All the nodes at the same level of an empty tree have the same hash, + * which can be computed from the default value of the leaves. This is + * stored in the [uncommitted] list. + * + * Any subtree filled with default values is represented by the Empty + * constructor and given its height it's possible to compute its hash + * using the [uncommitted] list. + * + * The leaves are indexed by their position [pos], ranging from 0 to + * (2^h)-1. The encoding of [pos] limits the possible size of the tree. + * In any case the only valid height for the Sapling library is 32, so even + * if the library encodes positions as uint64, they never exceed uint32. + * + * The tree is incremental in the sense that leaves cannot be modified but + * only added and exclusively in successive positions. + * + * Given that elements are added and retrieved by position, it is possible + * to use this information to efficiently navigate the tree. + * Given a tree of height [h] and a position [pos], if pos < pow2 (h-1) only + * the left subtree needs to be inspected recursively. Otherwise only the + * right needs to be visited, decreasing [pos] by [pow2 (h-1)]. + * + * In order to avoid storing the height for each subtree (or worse + * recomputing it), each function with suffix `_height` expects the height + * of the tree as parameter. These functions are only for internal use and + * are later aliased by functions using the default height of a Sapling + * incremental Merkle tree. + * + * Each node of the tree is indexed starting from the root at index 1, + * followed by its left child at index 2, right child at index 3 and so on + * until the last leaf at index 2^(depth+1)-1, or in terms of height + * 2^(32 - height +1) -1. + * The functions left and right return the index of the left and right child + * of a node. + *) + + let pow2 h = Int64.(shift_left 1L h) + + let max_height = 32 + + let max_size = pow2 max_height + + let assert_node node height = + assert ( + let first_of_height = pow2 (max_height - height) in + let first_of_next_height = Int64.shift_left first_of_height 1 in + Compare.Int64.(node >= first_of_height && node < first_of_next_height) ) + + let assert_height height = + assert (Compare.Int.(height >= 0 && height <= max_height)) + + let assert_pos pos height = + assert (Compare.Int64.(pos >= 0L && pos <= pow2 height)) + + let default_root = H.uncommitted max_height + + let init = Storage.Sapling.commitments_init + + let get_root_height ctx id node height = + assert_node node height ; + assert_height height ; + Storage.Sapling.Commitments.find (ctx, id) node + >|=? function + | (ctx, None) -> + let hash = H.uncommitted height in + (ctx, hash) + | (ctx, Some hash) -> + (ctx, hash) + + let left node = Int64.mul node 2L + + let right node = Int64.(add (mul node 2L) 1L) + + (* Not tail-recursive *) + let rec split_at n l = + if Compare.Int64.(n = 0L) then ([], l) + else + match l with + | [] -> + ([], l) + | x :: xs -> + let (l1, l2) = split_at Int64.(pred n) xs in + (x :: l1, l2) + + (* [insert tree height pos cms] inserts the list of commitments + [cms] in the tree [tree] of height [height] at the next position [pos]. + Returns the context, the size of the added storage, and the hash of the + node. Not tail-recursive. + Pre: incremental tree /\ + size tree + List.length cms <= pow2 height /\ + pos = size tree /\ + Post: incremental tree /\ + to_list (insert tree height pos cms) = to_list t @ cms *) + let rec insert ctx id node height pos cms = + assert_node node height ; + assert_height height ; + assert_pos pos height ; + match (height, cms) with + | (_, []) -> + get_root_height ctx id node height >|=? fun (ctx, h) -> (ctx, 0, h) + | (0, [cm]) -> + let h = H.of_commitment cm in + Storage.Sapling.Commitments.init (ctx, id) node h + >|=? fun (ctx, size) -> (ctx, size, h) + | _ -> + let height = height - 1 in + ( if Compare.Int64.(pos < pow2 height) then + let at = Int64.(sub (pow2 height) pos) in + let (cml, cmr) = split_at at cms in + insert ctx id (left node) height pos cml + >>=? fun (ctx, size_l, hl) -> + insert ctx id (right node) height 0L cmr + >|=? fun (ctx, size_r, hr) -> (ctx, size_l + size_r, hl, hr) + else + get_root_height ctx id (left node) height + >>=? fun (ctx, hl) -> + let pos = Int64.(sub pos (pow2 height)) in + insert ctx id (right node) height pos cms + >|=? fun (ctx, size_r, hr) -> (ctx, size_r, hl, hr) ) + >>=? fun (ctx, size_children, hl, hr) -> + let h = H.merkle_hash ~height hl hr in + Storage.Sapling.Commitments.add (ctx, id) node h + >|=? fun (ctx, size, _existing) -> (ctx, size + size_children, h) + + let rec fold_from_height ctx id node ~pos ~f ~acc height = + assert_node node height ; + assert_height height ; + assert_pos pos height ; + Storage.Sapling.Commitments.find (ctx, id) node + (* we don't count gas for this function, it is called only by RPC *) + >>=? function + | (_ctx, None) -> + return acc + | (_ctx, Some h) -> + if Compare.Int.(height = 0) then return (f acc h) + else + let full = pow2 (height - 1) in + if Compare.Int64.(pos < full) then + fold_from_height ctx id (left node) ~pos ~f ~acc (height - 1) + >>=? fun acc -> + (* Setting pos to 0 folds on the whole right subtree *) + fold_from_height ctx id (right node) ~pos:0L ~f ~acc (height - 1) + else + let pos = Int64.(sub pos full) in + fold_from_height ctx id (right node) ~pos ~f ~acc (height - 1) + + let root_node = 1L + + let get_root ctx id = get_root_height ctx id root_node max_height + + (* Expects pos to be the next position to insert. Pos is also the number of + inserted leaves. + A commitment should always be added together with a corresponding + ciphertext in the same position. + [insert] is not tail-recursive so we put a hard limit on the size of the + list of commitments. The use of [split_at] has O(n logn) complexity that is + less relevant on a smaller list. *) + let add ctx id cms pos = + let l = List.length cms in + assert (Compare.Int.(l <= 1000)) ; + let n' = Int64.(add pos (of_int l)) in + assert (Compare.Int64.(n' <= max_size)) ; + insert ctx id root_node max_height pos cms + >|=? fun (ctx, size, _h) -> (ctx, size) + + let get_from ctx id pos = + fold_from_height + ctx + id + root_node + ~pos + ~f:(fun acc c -> H.to_commitment c :: acc) + ~acc:[] + max_height + >|=? fun l -> List.rev l +end + +module Ciphertexts = struct + let init ctx id = Storage.Sapling.ciphertexts_init ctx id + + (* a ciphertext should always be added together with a corresponding + commitment in the same position *) + let add ctx id c pos = Storage.Sapling.Ciphertexts.init (ctx, id) pos c + + let get_from ctx id offset = + let rec aux (ctx, acc) pos = + Storage.Sapling.Ciphertexts.find (ctx, id) pos + >>=? fun (ctx, c) -> + match c with + | None -> + return (ctx, List.rev acc) + | Some c -> + aux (ctx, c :: acc) (Int64.succ pos) + in + aux (ctx, []) offset +end + +(* Collection of nullifiers w/o duplicates, append-only. It has a dual + implementation with a hash map for constant `mem` and with a ordered set to + retrieve by position. *) +module Nullifiers = struct + let init = Storage.Sapling.nullifiers_init + + let size ctx id = Storage.Sapling.Nullifiers_size.get (ctx, id) + + let mem ctx id nf = Storage.Sapling.Nullifiers_hashed.mem (ctx, id) nf + + (* Allows for duplicates as they are already checked by verify_update before + updating the state. + Not tail-recursive so we put a hard limit on the size of the + list of nullifiers. *) + let add ctx id nfs = + assert (Compare.Int.(List.length nfs <= 1000)) ; + size ctx id + >>=? fun nf_start_pos -> + fold_right_s + (fun nf (ctx, pos, acc_size) -> + Storage.Sapling.Nullifiers_hashed.init (ctx, id) nf + >>=? fun (ctx, size) -> + Storage.Sapling.Nullifiers_ordered.init (ctx, id) pos nf + >|=? fun ctx -> (ctx, Int64.succ pos, Z.add acc_size (Z.of_int size))) + nfs + (ctx, nf_start_pos, Z.zero) + >>=? fun (ctx, nf_end_pos, size) -> + Storage.Sapling.Nullifiers_size.update (ctx, id) nf_end_pos + >|=? fun ctx -> (ctx, size) + + let get_from ctx id offset = + let rec aux acc pos = + Storage.Sapling.Nullifiers_ordered.find (ctx, id) pos + >>=? function + | None -> + return @@ List.rev acc + | Some c -> + aux (c :: acc) (Int64.succ pos) + in + aux [] offset +end + +(** Bounded queue of roots. The full size is initialized with the default + uncommitted root, that's why roots storage doesn't need to be carbonated. + A maximum of one new root is added per protocol level. + If multiple transactions for the same shielded pool are processed during the + same contract call or several calls in the same block, only the last root + will be stored. + This property prevents transactions in the same block from depending on each + other and guarantees that a transaction will be valid for a least two hours + (hence the 120 size) after being forged. *) +module Roots = struct + let size = 120l + + (* pos is the index of the last inserted element *) + + let get ctx id = + Storage.Sapling.Roots_pos.get (ctx, id) + >>=? fun pos -> Storage.Sapling.Roots.get (ctx, id) pos + + let init ctx id = + let rec aux ctx pos = + if Compare.Int32.(pos < 0l) then return ctx + else + Storage.Sapling.Roots.init (ctx, id) pos Commitments.default_root + >>=? fun ctx -> aux ctx (Int32.pred pos) + in + aux ctx (Int32.pred size) + >>=? fun ctx -> + Storage.Sapling.Roots_pos.init (ctx, id) 0l + >>=? fun ctx -> + let level = (Raw_context.current_level ctx).level in + Storage.Sapling.Roots_level.init (ctx, id) level + + let mem ctx id root = + Storage.Sapling.Roots_pos.get (ctx, id) + >>=? fun start_pos -> + let rec aux pos = + Storage.Sapling.Roots.get (ctx, id) pos + >>=? fun hash -> + if Compare.Int.(Sapling.Hash.compare hash root = 0) then return true + else + let pos = Int32.(pred pos) in + let pos = if Compare.Int32.(pos < 0l) then Int32.pred size else pos in + if Compare.Int32.(pos = start_pos) then return false else aux pos + in + aux start_pos + + (* allows duplicates *) + let add ctx id root = + Storage.Sapling.Roots_pos.get (ctx, id) + >>=? fun pos -> + let level = (Raw_context.current_level ctx).level in + Storage.Sapling.Roots_level.get (ctx, id) + >>=? fun stored_level -> + if Raw_level_repr.(stored_level = level) then + (* if there is another add during the same level, it will over-write on + the same position *) + Storage.Sapling.Roots.add (ctx, id) pos root >|= ok + else + (* it's the first add for this level *) + (* TODO(samoht): why is it using [update] and not [init] then? *) + Storage.Sapling.Roots_level.update (ctx, id) level + >>=? fun ctx -> + let pos = Int32.rem (Int32.succ pos) size in + Storage.Sapling.Roots_pos.update (ctx, id) pos + >>=? fun ctx -> Storage.Sapling.Roots.add (ctx, id) pos root >|= ok +end + +(** This type links the permanent state stored in the context at the specified + id together with the ephemeral diff managed by the Michelson + interpreter. After a successful execution the diff can be applied to update + the state at id. The first time a state is created its id is None, one will + be assigned after the first application. *) +type state = { + id : Lazy_storage_kind.Sapling_state.Id.t option; + diff : Sapling_repr.diff; + memo_size : Sapling_repr.Memo_size.t; +} + +let empty_diff = + Sapling_repr.{commitments_and_ciphertexts = []; nullifiers = []} + +let empty_state ?id ~memo_size () = {id; diff = empty_diff; memo_size} + +(** Returns a state from an existing id. *) +let state_from_id ctxt id = + Storage.Sapling.Memo_size.get (ctxt, id) + >|=? fun memo_size -> ({id = Some id; diff = empty_diff; memo_size}, ctxt) + +let rpc_arg = Storage.Sapling.rpc_arg + +let get_memo_size ctx id = Storage.Sapling.Memo_size.get (ctx, id) + +let init ctx id ~memo_size = + Storage.Sapling.Memo_size.add (ctx, id) memo_size + >>= fun ctx -> + Storage.Sapling.Commitments_size.add (ctx, id) Int64.zero + >>= fun ctx -> + Commitments.init ctx id + >>= fun ctx -> + Nullifiers.init ctx id + >>= fun ctx -> + Roots.init ctx id >>=? fun ctx -> Ciphertexts.init ctx id >|= ok + +(* Gas costs for apply_diff. *) +let sapling_apply_diff_cost ~inputs ~outputs = + let open Saturation_repr in + add + (safe_int 1_300_000) + (add + (scale_fast (mul_safe_of_int_exn 5_000) (safe_int inputs)) + (scale_fast (mul_safe_of_int_exn 55_000) (safe_int outputs))) + +(** Applies a diff to a state id stored in the context. Updates Commitments, + Ciphertexts and Nullifiers using the diff and updates the Roots using the + new Commitments tree. *) +let apply_diff ctx id diff = + let open Sapling_repr in + let nb_commitments = List.length diff.commitments_and_ciphertexts in + let nb_nullifiers = List.length diff.nullifiers in + let sapling_cost = + sapling_apply_diff_cost ~inputs:nb_nullifiers ~outputs:nb_commitments + in + Raw_context.consume_gas ctx sapling_cost + >>?= fun ctx -> + Storage.Sapling.Commitments_size.get (ctx, id) + >>=? fun cm_start_pos -> + let cms = List.rev_map fst diff.commitments_and_ciphertexts in + Commitments.add ctx id cms cm_start_pos + >>=? fun (ctx, size) -> + Storage.Sapling.Commitments_size.update + (ctx, id) + (Int64.add cm_start_pos (Int64.of_int nb_commitments)) + >>=? fun ctx -> + fold_right_s + (fun (_cm, cp) (ctx, pos, acc_size) -> + Ciphertexts.add ctx id cp pos + >|=? fun (ctx, size) -> + (ctx, Int64.succ pos, Z.add acc_size (Z.of_int size))) + diff.commitments_and_ciphertexts + (ctx, cm_start_pos, Z.of_int size) + >>=? fun (ctx, _ct_end_pos, size) -> + Nullifiers.add ctx id diff.nullifiers + >>=? fun (ctx, size_nf) -> + let size = Z.add size size_nf in + match diff.commitments_and_ciphertexts with + | [] -> + (* avoids adding duplicates to Roots *) + return (ctx, size) + | _ :: _ -> + Commitments.get_root ctx id + >>=? fun (ctx, root) -> Roots.add ctx id root >|=? fun ctx -> (ctx, size) + +let add {id; diff; memo_size} cm_cipher_list = + assert ( + List.for_all + (fun (_cm, cipher) -> + Compare.Int.(Sapling.Ciphertext.get_memo_size cipher = memo_size)) + cm_cipher_list ) ; + { + id; + diff = + { + diff with + commitments_and_ciphertexts = + List.rev cm_cipher_list @ diff.commitments_and_ciphertexts; + }; + memo_size; + } + +let root_mem ctx {id} tested_root = + match id with + | Some id -> + Roots.mem ctx id tested_root + | None -> + return + Compare.Int.( + Sapling.Hash.compare tested_root Commitments.default_root = 0) + +(* to avoid a double spend we need to check the disk AND the diff *) +let nullifiers_mem ctx {id; diff} nf = + let exists_in_diff = + List.exists + (fun v -> Compare.Int.(Sapling.Nullifier.compare nf v = 0)) + diff.nullifiers + in + if exists_in_diff then return (ctx, true) + else + match id with + | None -> + return (ctx, false) + | Some id -> + Nullifiers.mem ctx id nf + +(* Allows for duplicates as they are already checked by verify_update before + updating the state. *) +let nullifiers_add {id; diff; memo_size} nf = + {id; diff = {diff with nullifiers = nf :: diff.nullifiers}; memo_size} + +type root = Sapling.Hash.t + +let root_encoding = Sapling.Hash.encoding + +let get_diff ctx id ?(offset_commitment = 0L) ?(offset_nullifier = 0L) () = + if + not + Sapling.Commitment.( + valid_position offset_commitment && valid_position offset_nullifier) + then failwith "Invalid argument." + else + Commitments.get_from ctx id offset_commitment + >>=? fun commitments -> + Roots.get ctx id + >>=? fun root -> + Nullifiers.get_from ctx id offset_nullifier + >>=? fun nullifiers -> + Ciphertexts.get_from ctx id offset_commitment + (* we don't count gas for RPCs *) + >|=? fun (_ctx, ciphertexts) -> + let commitments_and_ciphertexts = List.combine commitments ciphertexts in + (root, Sapling_repr.{commitments_and_ciphertexts; nullifiers}) diff --git a/src/proto_009_PsFLoren/lib_protocol/sapling_validator.ml b/src/proto_009_PsFLoren/lib_protocol/sapling_validator.ml new file mode 100644 index 0000000000000000000000000000000000000000..bafb7df54e7103cbf0f43e05a2b03cca3168e4c5 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/sapling_validator.ml @@ -0,0 +1,110 @@ +(* The MIT License (MIT) + * + * Copyright (c) 2019-2020 Nomadic Labs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. *) + +(* Check that each nullifier is not already present in the state and add it. + Important to avoid spending the same input twice in a transaction. *) +let rec check_and_update_nullifiers ctxt state inputs = + match inputs with + | [] -> + return (ctxt, Some state) + | input :: inputs -> ( + Sapling_storage.nullifiers_mem ctxt state Sapling.UTXO.(input.nf) + >>=? function + | (ctxt, true) -> + return (ctxt, None) + | (ctxt, false) -> + let state = + Sapling_storage.nullifiers_add state Sapling.UTXO.(input.nf) + in + check_and_update_nullifiers ctxt state inputs ) + +let verify_update : + Raw_context.t -> + Sapling_storage.state -> + Sapling_repr.transaction -> + string -> + (Raw_context.t * (Int64.t * Sapling_storage.state) option) tzresult Lwt.t = + fun ctxt state transaction key -> + (* Check the transaction *) + (* To avoid overflowing the balance, the number of inputs and outputs must be + bounded. + Ciphertexts' memo_size must match the state's memo_size. + These constraints are already enforced at the encoding level. *) + assert (Compare.Int.(List.compare_length_with transaction.inputs 5208 <= 0)) ; + assert (Compare.Int.(List.compare_length_with transaction.outputs 2019 <= 0)) ; + let pass = + List.for_all + (fun output -> + Compare.Int.( + Sapling.Ciphertext.get_memo_size Sapling.UTXO.(output.ciphertext) + = state.memo_size)) + transaction.outputs + in + if not pass then return (ctxt, None) + else + (* Check the root is a recent state *) + Sapling_storage.root_mem ctxt state transaction.root + >>=? fun pass -> + if not pass then return (ctxt, None) + else + check_and_update_nullifiers ctxt state transaction.inputs + >|=? function + | (ctxt, None) -> + (ctxt, None) + | (ctxt, Some state) -> + Sapling.Verification.with_verification_ctx (fun vctx -> + let pass = + (* Check all the output ZK proofs *) + List.for_all + (fun output -> Sapling.Verification.check_output vctx output) + transaction.outputs + in + if not pass then (ctxt, None) + else + let pass = + (* Check all the input Zk proofs and signatures *) + List.for_all + (fun input -> + Sapling.Verification.check_spend + vctx + input + transaction.root + key) + transaction.inputs + in + if not pass then (ctxt, None) + else + let pass = + (* Check the signature and balance of the whole transaction *) + Sapling.Verification.final_check vctx transaction key + in + if not pass then (ctxt, None) + else + (* update tree *) + let list_to_add = + List.map + (fun output -> + Sapling.UTXO.(output.cm, output.ciphertext)) + transaction.outputs + in + let state = Sapling_storage.add state list_to_add in + (ctxt, Some (transaction.balance, state))) diff --git a/src/proto_009_PsFLoren/lib_protocol/saturation_repr.ml b/src/proto_009_PsFLoren/lib_protocol/saturation_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..a09c3e5c8519a4ba3f5230e62ee851749b594094 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/saturation_repr.ml @@ -0,0 +1,143 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* let () = assert (Sys.int_size = 63) *) + +type _ t = int + +type mul_safe + +type may_saturate + +let may_saturate : _ t -> may_saturate t = fun x -> x + +let to_int x = x + +let ( < ) : _ t -> _ t -> bool = Compare.Int.( < ) + +let ( <= ) : _ t -> _ t -> bool = Compare.Int.( <= ) + +let ( > ) : _ t -> _ t -> bool = Compare.Int.( > ) + +let ( >= ) : _ t -> _ t -> bool = Compare.Int.( >= ) + +let ( = ) : _ t -> _ t -> bool = Compare.Int.( = ) + +let equal = ( = ) + +let ( <> ) : _ t -> _ t -> bool = Compare.Int.( <> ) + +let max : _ t -> _ t -> _ t = fun x y -> if x >= y then x else y + +let min : _ t -> _ t -> _ t = fun x y -> if x >= y then y else x + +let compare : _ t -> _ t -> _ t = Compare.Int.compare + +let saturated = max_int + +let of_int_opt t = if t >= 0 && t < saturated then Some t else None + +let of_z_opt z = + match Z.to_int z with int -> of_int_opt int | exception Z.Overflow -> None + +let to_z x = Z.of_int x + +let saturate_if_undef = function None -> saturated | Some x -> x + +let safe_int x = of_int_opt x |> saturate_if_undef + +let zero = 0 + +let small_enough z = + (* The following literal triggers an error if compiled under 32-bit + architectures, please do not modify it. This is a static way to + ensure that this file is compiled under a 64-bit architecture. *) + z land 0x7fffffff80000000 = 0 + +let mul_safe x = if small_enough x then Some x else None + +let mul_safe_exn x = + if small_enough x then x + else failwith (Format.sprintf "mul_safe_exn: %d must be below 2147483648" x) + +let mul_safe_of_int_exn x = + Option.bind (of_int_opt x) mul_safe + |> function + | None -> + failwith + (Format.sprintf "mul_safe_of_int_exn: %d must be below 2147483648" x) + | Some x -> + x + +(* If [x] is positive, shifting to the right will produce a number + which is positive and is less than [x]. *) +let shift_right x y = (x :> int) lsr y + +let mul x y = + (* assert (x >= 0 && y >= 0); *) + match x with + | 0 -> + 0 + | x -> + if small_enough x && small_enough y then x * y + else if Compare.Int.(y > saturated / x) then saturated + else x * y + +let mul_fast x y = x * y + +let scale_fast x y = + if x = 0 then 0 + else if small_enough y then x * y + else if Compare.Int.(y > saturated / x) then saturated + else x * y + +let add x y = + let z = x + y in + if z >= 0 then z else saturated + +let sub x y = Compare.Int.max (x - y) 0 + +let sub_opt x y = + let s = x - y in + if Compare.Int.(s >= 0) then Some s else None + +(* Notice that Z.erem does not behave as mod on negative numbers. + Fortunately, the inhabitant of [t] are non-negative. *) +let erem x y = x mod y + +let ediv x y = x / y + +let t_to_z_exn z = + match of_z_opt z with + | None -> + (* since the encoding is applied to values of type [t]. *) assert false + | Some x -> + x + +let z_encoding = Data_encoding.(check_size 9 (conv to_z t_to_z_exn z)) + +let n_encoding = Data_encoding.(check_size 9 (conv to_z t_to_z_exn n)) + +let pp fmt x = Format.pp_print_int fmt x diff --git a/src/proto_009_PsFLoren/lib_protocol/saturation_repr.mli b/src/proto_009_PsFLoren/lib_protocol/saturation_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..4ef8539ef8c5b960596ea7257a1ddabd9c650dbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/saturation_repr.mli @@ -0,0 +1,189 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides saturated arithmetic between 0 and 2^62 - 1. + + This means that the arithmetic operations provided by this module + do not overflow. If an operation would produce an integer [x] + greater than [2 ^ 62 - 1], it is [saturated] to this + value. Similarly, if an operation would produce a negative integer, + it outputs [zero] instead. + + This saturation arithmetic is used to monitor gas levels. While the + gas model can produce values beyond 2^62 - 1, there is no point in + distinguishing these values from 2^62 - 1 because the amount of gas + available is significantly lower than this limit. + + Notice that most saturation arithmetic operations do not behave + as their standard counterparts when one of their operands is + saturated. For instance, + + (saturated + saturated) - saturated = 0 + + For more information about saturation arithmetic, take a look at: + + https://en.wikipedia.org/wiki/Saturation_arithmetic + +*) + +(** An integer of type ['a t] is between [0] and [saturated]. + + The type parameter ['a] is [mul_safe] if the integer is known + not to overflow when multiplied with another [mul_safe t]. + + The type parameter ['a] is [may_saturate] if the integer is + not known to be sufficiently small to prevent overflow during + multiplication. + +*) +type 'a t = private int + +type mul_safe + +type may_saturate + +val may_saturate : _ t -> may_saturate t + +(** [to_int x] returns the underlying integer representing [x]. *) +val to_int : 'a t -> int + +(** 0 *) +val zero : _ t + +(** 2^62 - 1 *) +val saturated : may_saturate t + +(** We inherit the order over native integers. *) +val ( >= ) : _ t -> _ t -> bool + +val ( > ) : _ t -> _ t -> bool + +val ( <= ) : _ t -> _ t -> bool + +val ( < ) : _ t -> _ t -> bool + +val ( = ) : _ t -> _ t -> bool + +val ( <> ) : _ t -> _ t -> bool + +val equal : _ t -> _ t -> bool + +val min : 'a t -> 'a t -> 'a t + +val max : 'a t -> 'a t -> 'a t + +val compare : 'a t -> 'b t -> int + +(** [shift_right x y] behaves like a logical shift of [x] by [y] bits + to the right. [y] must be between 0 and 63. *) +val shift_right : 'a t -> int -> 'a t + +(** [mul x y] behaves like multiplication between native integers as + long as its result stay below [saturated]. Otherwise, [mul] returns + [saturated]. *) +val mul : _ t -> _ t -> may_saturate t + +(** [mul_safe x] returns a [mul_safe t] only if [x] does not trigger + overflows when multiplied with another [mul_safe t]. More precisely, + [x] is safe for fast multiplications if [x < 2147483648]. *) +val mul_safe : _ t -> mul_safe t option + +(** [mul_fast x y] exploits the fact that [x] and [y] are known not to + provoke overflows during multiplication to perform a mere + multiplication. *) +val mul_fast : mul_safe t -> mul_safe t -> may_saturate t + +(** [scale_fast x y] exploits the fact that [x] is known not to + provoke overflows during multiplication to perform a + multiplication faster than [mul]. *) +val scale_fast : mul_safe t -> _ t -> may_saturate t + +(** [add x y] behaves like addition between native integers as long as + its result stay below [saturated]. Otherwise, [add] returns + [saturated]. *) +val add : _ t -> _ t -> may_saturate t + +(** [sub x y] behaves like subtraction between native integers as long + as its result stay positive. Otherwise, [sub] returns [zero]. + This function assumes that [x] is not saturated. +*) +val sub : 'a t -> _ t -> 'a t + +(** [sub_opt x y] behaves like subtraction between native integers as + long as its result stay positive. Otherwise, [sub] returns + [None]. *) +val sub_opt : 'a t -> _ t -> 'a t option + +(** [ediv x y] returns [x / y]. This operation never saturates, hence + it is exactly the same as its native counterpart. [y] is supposed + to be strictly greater than 0, otherwise this function raises + [Division_by_zero]. *) +val ediv : 'a t -> _ t -> 'a t + +(** [erem x y] returns [x mod y]. [y] is supposed to be strictly + greater than 0, otherwise this function raises + [Division_by_zero]. *) +val erem : _ t -> 'b t -> 'b t + +(** [of_int_opt x] returns [Some x] if [x >= 0] and [x < saturated], + and [None] otherwise. *) +val of_int_opt : int -> may_saturate t option + +(** [of_z_opt x] returns [Some x] if [x >= 0] and [x < saturated], + and [None] otherwise. *) +val of_z_opt : Z.t -> may_saturate t option + +(** When a saturated integer is sufficiently small (i.e. strictly less + than 2147483648), we can assign it the type [mul_safe S.t] to use + it within fast multiplications, named [S.scale_fast] and + [S.mul_fast]. + + The following function allows such type assignment but may raise an + exception if the assumption is wrong. Therefore, [mul_safe_exn] + should only be used to define toplevel values, so that these + exceptions can only occur during startup. + *) +val mul_safe_exn : may_saturate t -> mul_safe t + +(** [mul_safe_of_int_exn x] is the composition of [of_int_opt] and + [mul_safe] in the option monad. This function raises [Invalid_argument] + if [x] is not safe. This function should be used on integer literals + that are obviously [mul_safe]. *) +val mul_safe_of_int_exn : int -> mul_safe t + +(** [safe_int x] is [of_int_opt x |> saturate_if_undef]. *) +val safe_int : int -> may_saturate t + +(** [to_z z] is [Z.of_int]. *) +val to_z : _ t -> Z.t + +(** Encoding for [t] through the encoding for [z] integers. *) +val z_encoding : _ t Data_encoding.t + +(** Encoding for [t] through the encoding for non-negative integers. *) +val n_encoding : _ t Data_encoding.t + +(** A pretty-printer for native integers. *) +val pp : Format.formatter -> _ t -> unit diff --git a/src/proto_009_PsFLoren/lib_protocol/script_expr_hash.ml b/src/proto_009_PsFLoren/lib_protocol/script_expr_hash.ml new file mode 100644 index 0000000000000000000000000000000000000000..2c7f93a04bb0a2e8a32bb081b035a5daff212984 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_expr_hash.ml @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let script_expr_hash = "\013\044\064\027" (* expr(54) *) + +include Blake2B.Make + (Base58) + (struct + let name = "script_expr" + + let title = "A script expression ID" + + let b58check_prefix = script_expr_hash + + let size = None + end) + +let () = Base58.check_encoded_prefix b58check_encoding "expr" 54 diff --git a/src/proto_009_PsFLoren/lib_protocol/script_expr_hash.mli b/src/proto_009_PsFLoren/lib_protocol/script_expr_hash.mli new file mode 100644 index 0000000000000000000000000000000000000000..5e374f2a38c0b0f7da05eaa33e91932d40e49838 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_expr_hash.mli @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include S.HASH diff --git a/src/proto_009_PsFLoren/lib_protocol/script_int_repr.ml b/src/proto_009_PsFLoren/lib_protocol/script_int_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..9ee84138091da2ac1a7d82a98457fb0597b683cd --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_int_repr.ml @@ -0,0 +1,104 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type n = Natural_tag + +type z = Integer_tag + +type 't num = Z.t + +let compare x y = Z.compare x y + +let zero = Z.zero + +let zero_n = Z.zero + +let to_string x = Z.to_string x + +let of_string s = try Some (Z.of_string s) with _ -> None + +let of_int32 n = Z.of_int64 @@ Int64.of_int32 n + +let to_int64 x = try Some (Z.to_int64 x) with _ -> None + +let of_int64 n = Z.of_int64 n + +let to_int x = try Some (Z.to_int x) with _ -> None + +let of_int n = Z.of_int n + +let of_zint x = x + +let to_zint x = x + +let add x y = Z.add x y + +let sub x y = Z.sub x y + +let mul x y = Z.mul x y + +let ediv x y = + try + let (q, r) = Z.ediv_rem x y in + Some (q, r) + with _ -> None + +let add_n = add + +let mul_n = mul + +let ediv_n = ediv + +let abs x = Z.abs x + +let is_nat x = if Compare.Z.(x < Z.zero) then None else Some x + +let neg x = Z.neg x + +let int x = x + +let shift_left x y = + if Compare.Int.(Z.compare y (Z.of_int 256) > 0) then None + else + let y = Z.to_int y in + Some (Z.shift_left x y) + +let shift_right x y = + if Compare.Int.(Z.compare y (Z.of_int 256) > 0) then None + else + let y = Z.to_int y in + Some (Z.shift_right x y) + +let shift_left_n = shift_left + +let shift_right_n = shift_right + +let logor x y = Z.logor x y + +let logxor x y = Z.logxor x y + +let logand x y = Z.logand x y + +let lognot x = Z.lognot x diff --git a/src/proto_009_PsFLoren/lib_protocol/script_int_repr.mli b/src/proto_009_PsFLoren/lib_protocol/script_int_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..c4c8c755a721804c4e7d104494202efea12d1f85 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_int_repr.mli @@ -0,0 +1,146 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The types for arbitrary precision integers in Michelson. + The type variable ['t] is always [n] or [z], + [n num] and [z num] are incompatible. + + This is internally a [Z.t]. + This module mostly adds signedness preservation guarantees. *) +type 't num [@@coq_phantom] + +(** Flag for natural numbers. *) +type n = Natural_tag + +(** Flag for relative numbers. *) +type z = Integer_tag + +(** Natural zero. *) +val zero_n : n num + +(** Relative zero. *) +val zero : z num + +(** Compare two numbers as if they were *) +val compare : 'a num -> 'a num -> int + +(** Conversion to an OCaml [string] in decimal notation. *) +val to_string : _ num -> string + +(** Conversion from an OCaml [string]. + Returns [None] in case of an invalid notation. + Supports [+] and [-] sign modifiers, and [0x], [0o] and [0b] base modifiers. *) +val of_string : string -> z num option + +(** Conversion from an OCaml [int32]. *) +val of_int32 : int32 -> z num + +(** Conversion to an OCaml [int64], returns [None] on overflow. *) +val to_int64 : _ num -> int64 option + +(** Conversion from an OCaml [int64]. *) +val of_int64 : int64 -> z num + +(** Conversion to an OCaml [int], returns [None] on overflow. *) +val to_int : _ num -> int option + +(** Conversion from an OCaml [int]. *) +val of_int : int -> z num + +(** Conversion from a Zarith integer ([Z.t]). *) +val of_zint : Z.t -> z num + +(** Conversion to a Zarith integer ([Z.t]). *) +val to_zint : 'a num -> Z.t + +(** Addition between naturals. *) +val add_n : n num -> n num -> n num + +(** Multiplication between naturals. *) +val mul_n : n num -> n num -> n num + +(** Euclidean division between naturals. + [ediv_n n d] returns [None] if divisor is zero, + or [Some (q, r)] where [n = d * q + r] and [[0 <= r < d]] otherwise. *) +val ediv_n : n num -> n num -> (n num * n num) option + +(** Sign agnostic addition. + Use {!add_n} when working with naturals to preserve the sign. *) +val add : _ num -> _ num -> z num + +(** Sign agnostic subtraction. + Use {!sub_n} when working with naturals to preserve the sign. *) +val sub : _ num -> _ num -> z num + +(** Sign agnostic multiplication. + Use {!mul_n} when working with naturals to preserve the sign. *) +val mul : _ num -> _ num -> z num + +(** Sign agnostic euclidean division. + [ediv n d] returns [None] if divisor is zero, + or [Some (q, r)] where [n = d * q + r] and [[0 <= r < |d|]] otherwise. + Use {!ediv_n} when working with naturals to preserve the sign. *) +val ediv : _ num -> _ num -> (z num * n num) option + +(** Compute the absolute value of a relative, turning it into a natural. *) +val abs : z num -> n num + +(** Partial identity over [N]. *) +val is_nat : z num -> n num option + +(** Negates a number. *) +val neg : _ num -> z num + +(** Turns a natural into a relative, not changing its value. *) +val int : n num -> z num + +(** Reverses each bit in the representation of the number. + Also applies to the sign. *) +val lognot : _ num -> z num + +(** Shifts the natural to the left of a number of bits between 0 and 256. + Returns [None] if the amount is too high. *) +val shift_left_n : n num -> n num -> n num option + +(** Shifts the natural to the right of a number of bits between 0 and 256. + Returns [None] if the amount is too high. *) +val shift_right_n : n num -> n num -> n num option + +(** Shifts the number to the left of a number of bits between 0 and 256. + Returns [None] if the amount is too high. *) +val shift_left : 'a num -> n num -> 'a num option + +(** Shifts the number to the right of a number of bits between 0 and 256. + Returns [None] if the amount is too high. *) +val shift_right : 'a num -> n num -> 'a num option + +(** Applies a boolean or operation to each bit. *) +val logor : 'a num -> 'a num -> 'a num + +(** Applies a boolean and operation to each bit. *) +val logand : _ num -> n num -> n num + +(** Applies a boolean xor operation to each bit. *) +val logxor : n num -> n num -> n num diff --git a/src/proto_009_PsFLoren/lib_protocol/script_interpreter.ml b/src/proto_009_PsFLoren/lib_protocol/script_interpreter.ml new file mode 100644 index 0000000000000000000000000000000000000000..7e54575f444da1a5a7a918eb95fc40e9c6240103 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_interpreter.ml @@ -0,0 +1,1553 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script +open Script_typed_ir +open Script_ir_translator +module S = Saturation_repr + +(* ---- Run-time errors -----------------------------------------------------*) + +type execution_trace = + (Script.location * Gas.t * (Script.expr * string option) list) list + +type error += + | Reject of Script.location * Script.expr * execution_trace option + +type error += Overflow of Script.location * execution_trace option + +type error += Runtime_contract_error : Contract.t * Script.expr -> error + +type error += Bad_contract_parameter of Contract.t (* `Permanent *) + +type error += Cannot_serialize_failure + +type error += Cannot_serialize_storage + +type error += Michelson_too_many_recursive_calls + +let () = + let open Data_encoding in + let trace_encoding = + list + @@ obj3 + (req "location" Script.location_encoding) + (req "gas" Gas.encoding) + (req + "stack" + (list (obj2 (req "item" Script.expr_encoding) (opt "annot" string)))) + in + (* Reject *) + register_error_kind + `Temporary + ~id:"michelson_v1.script_rejected" + ~title:"Script failed" + ~description:"A FAILWITH instruction was reached" + (obj3 + (req "location" Script.location_encoding) + (req "with" Script.expr_encoding) + (opt "trace" trace_encoding)) + (function Reject (loc, v, trace) -> Some (loc, v, trace) | _ -> None) + (fun (loc, v, trace) -> Reject (loc, v, trace)) ; + (* Overflow *) + register_error_kind + `Temporary + ~id:"michelson_v1.script_overflow" + ~title:"Script failed (overflow error)" + ~description: + "A FAIL instruction was reached due to the detection of an overflow" + (obj2 + (req "location" Script.location_encoding) + (opt "trace" trace_encoding)) + (function Overflow (loc, trace) -> Some (loc, trace) | _ -> None) + (fun (loc, trace) -> Overflow (loc, trace)) ; + (* Runtime contract error *) + register_error_kind + `Temporary + ~id:"michelson_v1.runtime_error" + ~title:"Script runtime error" + ~description:"Toplevel error for all runtime script errors" + (obj2 + (req "contract_handle" Contract.encoding) + (req "contract_code" Script.expr_encoding)) + (function + | Runtime_contract_error (contract, expr) -> + Some (contract, expr) + | _ -> + None) + (fun (contract, expr) -> Runtime_contract_error (contract, expr)) ; + (* Bad contract parameter *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_contract_parameter" + ~title:"Contract supplied an invalid parameter" + ~description: + "Either no parameter was supplied to a contract with a non-unit \ + parameter type, a non-unit parameter was passed to an account, or a \ + parameter was supplied of the wrong type" + Data_encoding.(obj1 (req "contract" Contract.encoding)) + (function Bad_contract_parameter c -> Some c | _ -> None) + (fun c -> Bad_contract_parameter c) ; + (* Cannot serialize failure *) + register_error_kind + `Temporary + ~id:"michelson_v1.cannot_serialize_failure" + ~title:"Not enough gas to serialize argument of FAILWITH" + ~description: + "Argument of FAILWITH was too big to be serialized with the provided gas" + Data_encoding.empty + (function Cannot_serialize_failure -> Some () | _ -> None) + (fun () -> Cannot_serialize_failure) ; + (* Cannot serialize storage *) + register_error_kind + `Temporary + ~id:"michelson_v1.cannot_serialize_storage" + ~title:"Not enough gas to serialize execution storage" + ~description: + "The returned storage was too big to be serialized with the provided gas" + Data_encoding.empty + (function Cannot_serialize_storage -> Some () | _ -> None) + (fun () -> Cannot_serialize_storage) ; + (* Michelson Stack Overflow *) + register_error_kind + `Permanent + ~id:"michelson_v1.interp_too_many_recursive_calls" + ~title:"Too many recursive calls during interpretation" + ~description: + "Too many recursive calls were needed for interpretation of a Michelson \ + script" + Data_encoding.empty + (function Michelson_too_many_recursive_calls -> Some () | _ -> None) + (fun () -> Michelson_too_many_recursive_calls) + +(* ---- interpreter ---------------------------------------------------------*) + +module Interp_costs = Michelson_v1_gas.Cost_of.Interpreter + +let rec interp_stack_prefix_preserving_operation : + type fbef bef faft aft result. + (fbef -> (faft * result) tzresult Lwt.t) -> + (fbef, faft, bef, aft) stack_prefix_preservation_witness -> + bef -> + (aft * result) tzresult Lwt.t = + fun f n stk -> + match (n, stk) with + | ( Prefix + (Prefix + (Prefix + (Prefix + (Prefix + (Prefix + (Prefix + (Prefix + (Prefix + (Prefix + (Prefix + (Prefix (Prefix (Prefix (Prefix (Prefix n))))))))))))))), + ( v0, + ( v1, + ( v2, + ( v3, + ( v4, + ( v5, + ( v6, + (v7, (v8, (v9, (va, (vb, (vc, (vd, (ve, (vf, rest))))))))) + ) ) ) ) ) ) ) ) -> + interp_stack_prefix_preserving_operation f n rest + >|=? fun (rest', result) -> + ( ( v0, + ( v1, + ( v2, + ( v3, + ( v4, + ( v5, + ( v6, + ( v7, + (v8, (v9, (va, (vb, (vc, (vd, (ve, (vf, rest')))))))) + ) ) ) ) ) ) ) ), + result ) + | (Prefix (Prefix (Prefix (Prefix n))), (v0, (v1, (v2, (v3, rest))))) -> + interp_stack_prefix_preserving_operation f n rest + >|=? fun (rest', result) -> ((v0, (v1, (v2, (v3, rest')))), result) + | (Prefix n, (v, rest)) -> + interp_stack_prefix_preserving_operation f n rest + >|=? fun (rest', result) -> ((v, rest'), result) + | (Rest, v) -> + f v + +type step_constants = { + source : Contract.t; + payer : Contract.t; + self : Contract.t; + amount : Tez.t; + chain_id : Chain_id.t; +} + +module type STEP_LOGGER = sig + val log_interp : + context -> ('bef, 'aft) Script_typed_ir.descr -> 'bef -> unit + + val log_entry : context -> ('bef, 'aft) Script_typed_ir.descr -> 'bef -> unit + + val log_exit : context -> ('bef, 'aft) Script_typed_ir.descr -> 'aft -> unit + + val get_log : unit -> execution_trace option tzresult Lwt.t +end + +type logger = (module STEP_LOGGER) + +module No_trace : STEP_LOGGER = struct + let log_interp _ctxt _descr _stack = () + + let log_entry _ctxt _descr _stack = () + + let log_exit _ctxt _descr _stack = () + + let get_log () = return_none +end + +let cost_of_instr : type b a. (b, a) descr -> b -> Gas.cost = + fun descr stack -> + match (descr.instr, stack) with + | (Drop, _) -> + Interp_costs.drop + | (Dup, _) -> + Interp_costs.dup + | (Swap, _) -> + Interp_costs.swap + | (Const _, _) -> + Interp_costs.push + | (Cons_some, _) -> + Interp_costs.cons_some + | (Cons_none _, _) -> + Interp_costs.cons_none + | (If_none _, _) -> + Interp_costs.if_none + | (Cons_pair, _) -> + Interp_costs.cons_pair + | (Unpair, _) -> + Interp_costs.unpair + | (Car, _) -> + Interp_costs.car + | (Cdr, _) -> + Interp_costs.cdr + | (Cons_left, _) -> + Interp_costs.cons_left + | (Cons_right, _) -> + Interp_costs.cons_right + | (If_left _, _) -> + Interp_costs.if_left + | (Cons_list, _) -> + Interp_costs.cons_list + | (Nil, _) -> + Interp_costs.nil + | (If_cons _, _) -> + Interp_costs.if_cons + | (List_map _, (list, _)) -> + Interp_costs.list_map list + | (List_size, _) -> + Interp_costs.list_size + | (List_iter _, (l, _)) -> + Interp_costs.list_iter l + | (Empty_set _, _) -> + Interp_costs.empty_set + | (Set_iter _, (set, _)) -> + Interp_costs.set_iter set + | (Set_mem, (v, (set, _))) -> + Interp_costs.set_mem v set + | (Set_update, (v, (_, (set, _)))) -> + Interp_costs.set_update v set + | (Set_size, _) -> + Interp_costs.set_size + | (Empty_map _, _) -> + Interp_costs.empty_map + | (Map_map _, (map, _)) -> + Interp_costs.map_map map + | (Map_iter _, (map, _)) -> + Interp_costs.map_iter map + | (Map_mem, (v, (map, _rest))) -> + Interp_costs.map_mem v map + | (Map_get, (v, (map, _rest))) -> + Interp_costs.map_get v map + | (Map_update, (k, (_, (map, _)))) -> + Interp_costs.map_update k map + | (Map_get_and_update, (k, (_, (map, _)))) -> + Interp_costs.map_get_and_update k map + | (Map_size, _) -> + Interp_costs.map_size + | (Empty_big_map _, _) -> + Interp_costs.empty_map + | (Big_map_mem, (_, (map, _))) -> + Interp_costs.big_map_mem map.diff + | (Big_map_get, (_, (map, _))) -> + Interp_costs.big_map_get map.diff + | (Big_map_update, (_, (_, (map, _)))) -> + Interp_costs.big_map_update map.diff + | (Big_map_get_and_update, (_, (_, (map, _)))) -> + Interp_costs.big_map_get_and_update map.diff + | (Add_seconds_to_timestamp, (n, (t, _))) -> + Interp_costs.add_seconds_timestamp n t + | (Add_timestamp_to_seconds, (t, (n, _))) -> + Interp_costs.add_seconds_timestamp n t + | (Sub_timestamp_seconds, (t, (n, _))) -> + Interp_costs.sub_seconds_timestamp n t + | (Diff_timestamps, (t1, (t2, _))) -> + Interp_costs.diff_timestamps t1 t2 + | (Concat_string_pair, (x, (y, _))) -> + Interp_costs.concat_string_pair x y + | (Concat_string, (ss, _)) -> + Interp_costs.concat_string_precheck ss + | (Slice_string, (_offset, (_length, (s, _)))) -> + Interp_costs.slice_string s + | (String_size, _) -> + Interp_costs.string_size + | (Concat_bytes_pair, (x, (y, _))) -> + Interp_costs.concat_bytes_pair x y + | (Concat_bytes, (ss, _)) -> + Interp_costs.concat_string_precheck ss + | (Slice_bytes, (_offset, (_length, (s, _)))) -> + Interp_costs.slice_bytes s + | (Bytes_size, _) -> + Interp_costs.bytes_size + | (Add_tez, _) -> + Interp_costs.add_tez + | (Sub_tez, _) -> + Interp_costs.sub_tez + | (Mul_teznat, (_, (n, _))) -> + Interp_costs.mul_teznat n + | (Mul_nattez, (n, (_, _))) -> + Interp_costs.mul_teznat n + | (Or, _) -> + Interp_costs.bool_or + | (And, _) -> + Interp_costs.bool_and + | (Xor, _) -> + Interp_costs.bool_xor + | (Not, _) -> + Interp_costs.bool_not + | (Is_nat, _) -> + Interp_costs.is_nat + | (Abs_int, (x, _)) -> + Interp_costs.abs_int x + | (Int_nat, _) -> + Interp_costs.int_nat + | (Neg_int, (x, _)) -> + Interp_costs.neg_int x + | (Neg_nat, (x, _)) -> + Interp_costs.neg_nat x + | (Add_intint, (x, (y, _))) -> + Interp_costs.add_bigint x y + | (Add_intnat, (x, (y, _))) -> + Interp_costs.add_bigint x y + | (Add_natint, (x, (y, _))) -> + Interp_costs.add_bigint x y + | (Add_natnat, (x, (y, _))) -> + Interp_costs.add_bigint x y + | (Sub_int, (x, (y, _))) -> + Interp_costs.sub_bigint x y + | (Mul_intint, (x, (y, _))) -> + Interp_costs.mul_bigint x y + | (Mul_intnat, (x, (y, _))) -> + Interp_costs.mul_bigint x y + | (Mul_natint, (x, (y, _))) -> + Interp_costs.mul_bigint x y + | (Mul_natnat, (x, (y, _))) -> + Interp_costs.mul_bigint x y + | (Ediv_teznat, (x, (y, _))) -> + Interp_costs.ediv_teznat x y + | (Ediv_tez, _) -> + Interp_costs.ediv_tez + | (Ediv_intint, (x, (y, _))) -> + Interp_costs.ediv_bigint x y + | (Ediv_intnat, (x, (y, _))) -> + Interp_costs.ediv_bigint x y + | (Ediv_natint, (x, (y, _))) -> + Interp_costs.ediv_bigint x y + | (Ediv_natnat, (x, (y, _))) -> + Interp_costs.ediv_bigint x y + | (Lsl_nat, (x, _)) -> + Interp_costs.lsl_nat x + | (Lsr_nat, (x, _)) -> + Interp_costs.lsr_nat x + | (Or_nat, (x, (y, _))) -> + Interp_costs.or_nat x y + | (And_nat, (x, (y, _))) -> + Interp_costs.and_nat x y + | (And_int_nat, (x, (y, _))) -> + Interp_costs.and_nat x y + | (Xor_nat, (x, (y, _))) -> + Interp_costs.xor_nat x y + | (Not_int, (x, _)) -> + Interp_costs.not_nat x + | (Not_nat, (x, _)) -> + Interp_costs.not_nat x + | (Seq _, _) -> + Interp_costs.seq + | (If _, _) -> + Interp_costs.if_ + | (Loop _, _) -> + Interp_costs.loop + | (Loop_left _, _) -> + Interp_costs.loop_left + | (Dip _, _) -> + Interp_costs.dip + | (Exec, _) -> + Interp_costs.exec + | (Apply _, _) -> + Interp_costs.apply + | (Lambda _, _) -> + Interp_costs.push + | (Failwith _, _) -> + Gas.free + | (Nop, _) -> + Interp_costs.nop + | (Compare ty, (a, (b, _))) -> + Interp_costs.compare ty a b + | (Eq, _) -> + Interp_costs.neq + | (Neq, _) -> + Interp_costs.neq + | (Lt, _) -> + Interp_costs.neq + | (Le, _) -> + Interp_costs.neq + | (Gt, _) -> + Interp_costs.neq + | (Ge, _) -> + Interp_costs.neq + | (Pack _, _) -> + Gas.free + | (Unpack _, _) -> + Gas.free + | (Address, _) -> + Interp_costs.address + | (Contract _, _) -> + Interp_costs.contract + | (Transfer_tokens, _) -> + Interp_costs.transfer_tokens + | (Implicit_account, _) -> + Interp_costs.implicit_account + | (Set_delegate, _) -> + Interp_costs.set_delegate + | (Balance, _) -> + Interp_costs.balance + | (Level, _) -> + Interp_costs.level + | (Now, _) -> + Interp_costs.now + | (Check_signature, (key, (_, (message, _)))) -> + Interp_costs.check_signature key message + | (Hash_key, (pk, _)) -> + Interp_costs.hash_key pk + | (Blake2b, (bytes, _)) -> + Interp_costs.blake2b bytes + | (Sha256, (bytes, _)) -> + Interp_costs.sha256 bytes + | (Sha512, (bytes, _)) -> + Interp_costs.sha512 bytes + | (Source, _) -> + Interp_costs.source + | (Sender, _) -> + Interp_costs.source + | (Self _, _) -> + Interp_costs.self + | (Self_address, _) -> + Interp_costs.self + | (Amount, _) -> + Interp_costs.amount + | (Dig (n, _), _) -> + Interp_costs.dign n + | (Dug (n, _), _) -> + Interp_costs.dugn n + | (Dipn (n, _, _), _) -> + Interp_costs.dipn n + | (Dropn (n, _), _) -> + Interp_costs.dropn n + | (ChainId, _) -> + Interp_costs.chain_id + | (Create_contract _, _) -> + Interp_costs.create_contract + | (Never, (_, _)) -> + . + | (Voting_power, _) -> + Interp_costs.voting_power + | (Total_voting_power, _) -> + Interp_costs.total_voting_power + | (Keccak, (bytes, _)) -> + Interp_costs.keccak bytes + | (Sha3, (bytes, _)) -> + Interp_costs.sha3 bytes + | (Add_bls12_381_g1, _) -> + Interp_costs.add_bls12_381_g1 + | (Add_bls12_381_g2, _) -> + Interp_costs.add_bls12_381_g2 + | (Add_bls12_381_fr, _) -> + Interp_costs.add_bls12_381_fr + | (Mul_bls12_381_g1, _) -> + Interp_costs.mul_bls12_381_g1 + | (Mul_bls12_381_g2, _) -> + Interp_costs.mul_bls12_381_g2 + | (Mul_bls12_381_fr, _) -> + Interp_costs.mul_bls12_381_fr + | (Mul_bls12_381_fr_z, _) -> + Interp_costs.mul_bls12_381_fr_z + | (Mul_bls12_381_z_fr, _) -> + Interp_costs.mul_bls12_381_fr_z + | (Int_bls12_381_fr, _) -> + Interp_costs.int_bls12_381_fr + | (Neg_bls12_381_g1, _) -> + Interp_costs.neg_bls12_381_g1 + | (Neg_bls12_381_g2, _) -> + Interp_costs.neg_bls12_381_g2 + | (Neg_bls12_381_fr, _) -> + Interp_costs.neg_bls12_381_fr + | (Pairing_check_bls12_381, (pairs, _)) -> + Interp_costs.pairing_check_bls12_381 pairs + | (Comb (n, _), _) -> + Interp_costs.comb n + | (Uncomb (n, _), _) -> + Interp_costs.uncomb n + | (Comb_get (n, _), _) -> + Interp_costs.comb_get n + | (Comb_set (n, _), _) -> + Interp_costs.comb_set n + | (Dup_n (n, _), _) -> + Interp_costs.dupn n + | (Sapling_empty_state _, _) -> + Interp_costs.sapling_empty_state + | (Sapling_verify_update, (tx, _)) -> + let inputs = List.length tx.inputs in + let outputs = List.length tx.outputs in + Interp_costs.sapling_verify_update ~inputs ~outputs + | (Ticket, _) -> + Interp_costs.ticket + | (Read_ticket, _) -> + Interp_costs.read_ticket + | (Split_ticket, (ticket, ((amount_a, amount_b), _))) -> + Interp_costs.split_ticket ticket.amount amount_a amount_b + | (Join_tickets ty, ((ticket_a, ticket_b), _)) -> + Interp_costs.join_tickets ty ticket_a ticket_b + +let unpack ctxt ~ty ~bytes = + Gas.check_enough ctxt (Script.serialized_cost bytes) + >>?= fun () -> + if + Compare.Int.(Bytes.length bytes >= 1) + && Compare.Int.(TzEndian.get_uint8 bytes 0 = 0x05) + then + let bytes = Bytes.sub bytes 1 (Bytes.length bytes - 1) in + match Data_encoding.Binary.of_bytes Script.expr_encoding bytes with + | None -> + Lwt.return + ( Gas.consume ctxt (Interp_costs.unpack_failed bytes) + >|? fun ctxt -> (None, ctxt) ) + | Some expr -> ( + Gas.consume ctxt (Script.deserialized_cost expr) + >>?= fun ctxt -> + parse_data + ctxt + ~legacy:false + ~allow_forged:false + ty + (Micheline.root expr) + >|= function + | Ok (value, ctxt) -> + ok (Some value, ctxt) + | Error _ignored -> + Gas.consume ctxt (Interp_costs.unpack_failed bytes) + >|? fun ctxt -> (None, ctxt) ) + else return (None, ctxt) + +let rec step_bounded : + type b a. + logger -> + stack_depth:int -> + context -> + step_constants -> + (b, a) descr -> + b -> + (a * context) tzresult Lwt.t = + fun logger ~stack_depth ctxt step_constants ({instr; loc; _} as descr) stack -> + let gas = cost_of_instr descr stack in + Gas.consume ctxt gas + >>?= fun ctxt -> + let module Log = (val logger) in + Log.log_entry ctxt descr stack ; + let logged_return : a * context -> (a * context) tzresult Lwt.t = + fun (ret, ctxt) -> + Log.log_exit ctxt descr ret ; + return (ret, ctxt) + in + let non_terminal_recursion ~ctxt ?(stack_depth = stack_depth + 1) descr stack + = + if Compare.Int.(stack_depth >= 10_000) then + fail Michelson_too_many_recursive_calls + else step_bounded logger ~stack_depth ctxt step_constants descr stack + in + match (instr, stack) with + (* stack ops *) + | (Drop, (_, rest)) -> + logged_return (rest, ctxt) + | (Dup, (v, rest)) -> + logged_return ((v, (v, rest)), ctxt) + | (Swap, (vi, (vo, rest))) -> + logged_return ((vo, (vi, rest)), ctxt) + | (Const v, rest) -> + logged_return ((v, rest), ctxt) + (* options *) + | (Cons_some, (v, rest)) -> + logged_return ((Some v, rest), ctxt) + | (Cons_none _, rest) -> + logged_return ((None, rest), ctxt) + | (If_none (bt, _), (None, rest)) -> + step_bounded logger ~stack_depth ctxt step_constants bt rest + | (If_none (_, bf), (Some v, rest)) -> + step_bounded logger ~stack_depth ctxt step_constants bf (v, rest) + (* pairs *) + | (Cons_pair, (a, (b, rest))) -> + logged_return (((a, b), rest), ctxt) + | (Unpair, ((a, b), rest)) -> + logged_return ((a, (b, rest)), ctxt) + | (Car, ((a, _), rest)) -> + logged_return ((a, rest), ctxt) + | (Cdr, ((_, b), rest)) -> + logged_return ((b, rest), ctxt) + (* unions *) + | (Cons_left, (v, rest)) -> + logged_return ((L v, rest), ctxt) + | (Cons_right, (v, rest)) -> + logged_return ((R v, rest), ctxt) + | (If_left (bt, _), (L v, rest)) -> + step_bounded logger ~stack_depth ctxt step_constants bt (v, rest) + | (If_left (_, bf), (R v, rest)) -> + step_bounded logger ~stack_depth ctxt step_constants bf (v, rest) + (* lists *) + | (Cons_list, (hd, (tl, rest))) -> + logged_return ((list_cons hd tl, rest), ctxt) + | (Nil, rest) -> + logged_return ((list_empty, rest), ctxt) + | (If_cons (_, bf), ({elements = []; _}, rest)) -> + step_bounded logger ~stack_depth ctxt step_constants bf rest + | (If_cons (bt, _), ({elements = hd :: tl; length}, rest)) -> + let tl = {elements = tl; length = length - 1} in + step_bounded logger ~stack_depth ctxt step_constants bt (hd, (tl, rest)) + | (List_map body, (list, rest)) -> + let rec loop rest ctxt l acc = + match l with + | [] -> + let result = {elements = List.rev acc; length = list.length} in + return ((result, rest), ctxt) + | hd :: tl -> + non_terminal_recursion ~ctxt body (hd, rest) + >>=? fun ((hd, rest), ctxt) -> loop rest ctxt tl (hd :: acc) + in + loop rest ctxt list.elements [] + >>=? fun (res, ctxt) -> logged_return (res, ctxt) + | (List_size, (list, rest)) -> + logged_return ((Script_int.(abs (of_int list.length)), rest), ctxt) + | (List_iter body, (l, init)) -> + let rec loop ctxt l stack = + match l with + | [] -> + return (stack, ctxt) + | hd :: tl -> + non_terminal_recursion ~ctxt body (hd, stack) + >>=? fun (stack, ctxt) -> loop ctxt tl stack + in + loop ctxt l.elements init + >>=? fun (res, ctxt) -> logged_return (res, ctxt) + (* sets *) + | (Empty_set t, rest) -> + logged_return ((empty_set t, rest), ctxt) + | (Set_iter body, (set, init)) -> + let l = List.rev (set_fold (fun e acc -> e :: acc) set []) in + let rec loop ctxt l stack = + match l with + | [] -> + return (stack, ctxt) + | hd :: tl -> + non_terminal_recursion ~ctxt body (hd, stack) + >>=? fun (stack, ctxt) -> loop ctxt tl stack + in + loop ctxt l init >>=? fun (res, ctxt) -> logged_return (res, ctxt) + | (Set_mem, (v, (set, rest))) -> + logged_return ((set_mem v set, rest), ctxt) + | (Set_update, (v, (presence, (set, rest)))) -> + logged_return ((set_update v presence set, rest), ctxt) + | (Set_size, (set, rest)) -> + logged_return ((set_size set, rest), ctxt) + (* maps *) + | (Empty_map (t, _), rest) -> + logged_return ((empty_map t, rest), ctxt) + | (Map_map body, (map, rest)) -> + let l = List.rev (map_fold (fun k v acc -> (k, v) :: acc) map []) in + let rec loop rest ctxt l acc = + match l with + | [] -> + return ((acc, rest), ctxt) + | ((k, _) as hd) :: tl -> + non_terminal_recursion ~ctxt body (hd, rest) + >>=? fun ((hd, rest), ctxt) -> + loop rest ctxt tl (map_update k (Some hd) acc) + in + loop rest ctxt l (empty_map (map_key_ty map)) + >>=? fun (res, ctxt) -> logged_return (res, ctxt) + | (Map_iter body, (map, init)) -> + let l = List.rev (map_fold (fun k v acc -> (k, v) :: acc) map []) in + let rec loop ctxt l stack = + match l with + | [] -> + return (stack, ctxt) + | hd :: tl -> + non_terminal_recursion ~ctxt body (hd, stack) + >>=? fun (stack, ctxt) -> loop ctxt tl stack + in + loop ctxt l init >>=? fun (res, ctxt) -> logged_return (res, ctxt) + | (Map_mem, (v, (map, rest))) -> + logged_return ((map_mem v map, rest), ctxt) + | (Map_get, (v, (map, rest))) -> + logged_return ((map_get v map, rest), ctxt) + | (Map_update, (k, (v, (map, rest)))) -> + logged_return ((map_update k v map, rest), ctxt) + | (Map_get_and_update, (k, (v, (map, rest)))) -> + let map' = map_update k v map in + let v' = map_get k map in + logged_return ((v', (map', rest)), ctxt) + | (Map_size, (map, rest)) -> + logged_return ((map_size map, rest), ctxt) + (* Big map operations *) + | (Empty_big_map (tk, tv), rest) -> + logged_return ((Script_ir_translator.empty_big_map tk tv, rest), ctxt) + | (Big_map_mem, (key, (map, rest))) -> + Script_ir_translator.big_map_mem ctxt key map + >>=? fun (res, ctxt) -> logged_return ((res, rest), ctxt) + | (Big_map_get, (key, (map, rest))) -> + Script_ir_translator.big_map_get ctxt key map + >>=? fun (res, ctxt) -> logged_return ((res, rest), ctxt) + | (Big_map_update, (key, (maybe_value, (map, rest)))) -> + Script_ir_translator.big_map_update ctxt key maybe_value map + >>=? fun (res, ctxt) -> logged_return ((res, rest), ctxt) + | (Big_map_get_and_update, (k, (v, (map, rest)))) -> + Script_ir_translator.big_map_get_and_update ctxt k v map + >>=? fun (v', map', ctxt) -> logged_return ((v', (map', rest)), ctxt) + (* timestamp operations *) + | (Add_seconds_to_timestamp, (n, (t, rest))) -> + let result = Script_timestamp.add_delta t n in + logged_return ((result, rest), ctxt) + | (Add_timestamp_to_seconds, (t, (n, rest))) -> + let result = Script_timestamp.add_delta t n in + logged_return ((result, rest), ctxt) + | (Sub_timestamp_seconds, (t, (s, rest))) -> + let result = Script_timestamp.sub_delta t s in + logged_return ((result, rest), ctxt) + | (Diff_timestamps, (t1, (t2, rest))) -> + let result = Script_timestamp.diff t1 t2 in + logged_return ((result, rest), ctxt) + (* string operations *) + | (Concat_string_pair, (x, (y, rest))) -> + let s = String.concat "" [x; y] in + logged_return ((s, rest), ctxt) + | (Concat_string, (ss, rest)) -> + (* The cost for this fold_left has been paid upfront *) + let total_length = + List.fold_left + (fun acc s -> S.add acc (S.safe_int (String.length s))) + S.zero + ss.elements + in + Gas.consume ctxt (Interp_costs.concat_string total_length) + >>?= fun ctxt -> + let s = String.concat "" ss.elements in + logged_return ((s, rest), ctxt) + | (Slice_string, (offset, (length, (s, rest)))) -> + let s_length = Z.of_int (String.length s) in + let offset = Script_int.to_zint offset in + let length = Script_int.to_zint length in + if Compare.Z.(offset < s_length && Z.add offset length <= s_length) then + logged_return + ( (Some (String.sub s (Z.to_int offset) (Z.to_int length)), rest), + ctxt ) + else logged_return ((None, rest), ctxt) + | (String_size, (s, rest)) -> + logged_return ((Script_int.(abs (of_int (String.length s))), rest), ctxt) + (* bytes operations *) + | (Concat_bytes_pair, (x, (y, rest))) -> + let s = Bytes.cat x y in + logged_return ((s, rest), ctxt) + | (Concat_bytes, (ss, rest)) -> + (* The cost for this fold_left has been paid upfront *) + let total_length = + List.fold_left + (fun acc s -> S.add acc (S.safe_int (Bytes.length s))) + S.zero + ss.elements + in + Gas.consume ctxt (Interp_costs.concat_string total_length) + >>?= fun ctxt -> + let s = Bytes.concat Bytes.empty ss.elements in + logged_return ((s, rest), ctxt) + | (Slice_bytes, (offset, (length, (s, rest)))) -> + let s_length = Z.of_int (Bytes.length s) in + let offset = Script_int.to_zint offset in + let length = Script_int.to_zint length in + if Compare.Z.(offset < s_length && Z.add offset length <= s_length) then + logged_return + ((Some (Bytes.sub s (Z.to_int offset) (Z.to_int length)), rest), ctxt) + else logged_return ((None, rest), ctxt) + | (Bytes_size, (s, rest)) -> + logged_return ((Script_int.(abs (of_int (Bytes.length s))), rest), ctxt) + (* currency operations *) + | (Add_tez, (x, (y, rest))) -> + Tez.(x +? y) >>?= fun res -> logged_return ((res, rest), ctxt) + | (Sub_tez, (x, (y, rest))) -> + Tez.(x -? y) >>?= fun res -> logged_return ((res, rest), ctxt) + | (Mul_teznat, (x, (y, rest))) -> ( + match Script_int.to_int64 y with + | None -> + Log.get_log () >>=? fun log -> fail (Overflow (loc, log)) + | Some y -> + Tez.(x *? y) >>?= fun res -> logged_return ((res, rest), ctxt) ) + | (Mul_nattez, (y, (x, rest))) -> ( + match Script_int.to_int64 y with + | None -> + Log.get_log () >>=? fun log -> fail (Overflow (loc, log)) + | Some y -> + Tez.(x *? y) >>?= fun res -> logged_return ((res, rest), ctxt) ) + (* boolean operations *) + | (Or, (x, (y, rest))) -> + logged_return ((x || y, rest), ctxt) + | (And, (x, (y, rest))) -> + logged_return ((x && y, rest), ctxt) + | (Xor, (x, (y, rest))) -> + logged_return ((Compare.Bool.(x <> y), rest), ctxt) + | (Not, (x, rest)) -> + logged_return ((not x, rest), ctxt) + (* integer operations *) + | (Is_nat, (x, rest)) -> + logged_return ((Script_int.is_nat x, rest), ctxt) + | (Abs_int, (x, rest)) -> + logged_return ((Script_int.abs x, rest), ctxt) + | (Int_nat, (x, rest)) -> + logged_return ((Script_int.int x, rest), ctxt) + | (Neg_int, (x, rest)) -> + logged_return ((Script_int.neg x, rest), ctxt) + | (Neg_nat, (x, rest)) -> + logged_return ((Script_int.neg x, rest), ctxt) + | (Add_intint, (x, (y, rest))) -> + logged_return ((Script_int.add x y, rest), ctxt) + | (Add_intnat, (x, (y, rest))) -> + logged_return ((Script_int.add x y, rest), ctxt) + | (Add_natint, (x, (y, rest))) -> + logged_return ((Script_int.add x y, rest), ctxt) + | (Add_natnat, (x, (y, rest))) -> + logged_return ((Script_int.add_n x y, rest), ctxt) + | (Sub_int, (x, (y, rest))) -> + logged_return ((Script_int.sub x y, rest), ctxt) + | (Mul_intint, (x, (y, rest))) -> + logged_return ((Script_int.mul x y, rest), ctxt) + | (Mul_intnat, (x, (y, rest))) -> + logged_return ((Script_int.mul x y, rest), ctxt) + | (Mul_natint, (x, (y, rest))) -> + logged_return ((Script_int.mul x y, rest), ctxt) + | (Mul_natnat, (x, (y, rest))) -> + logged_return ((Script_int.mul_n x y, rest), ctxt) + | (Ediv_teznat, (x, (y, rest))) -> + let x = Script_int.of_int64 (Tez.to_mutez x) in + let result = + match Script_int.ediv x y with + | None -> + None + | Some (q, r) -> ( + match (Script_int.to_int64 q, Script_int.to_int64 r) with + | (Some q, Some r) -> ( + match (Tez.of_mutez q, Tez.of_mutez r) with + | (Some q, Some r) -> + Some (q, r) + (* Cannot overflow *) + | _ -> + assert false ) + (* Cannot overflow *) + | _ -> + assert false ) + in + logged_return ((result, rest), ctxt) + | (Ediv_tez, (x, (y, rest))) -> + let x = Script_int.abs (Script_int.of_int64 (Tez.to_mutez x)) in + let y = Script_int.abs (Script_int.of_int64 (Tez.to_mutez y)) in + let result = + match Script_int.ediv_n x y with + | None -> + None + | Some (q, r) -> ( + match Script_int.to_int64 r with + | None -> + assert false (* Cannot overflow *) + | Some r -> ( + match Tez.of_mutez r with + | None -> + assert false (* Cannot overflow *) + | Some r -> + Some (q, r) ) ) + in + logged_return ((result, rest), ctxt) + | (Ediv_intint, (x, (y, rest))) -> + logged_return ((Script_int.ediv x y, rest), ctxt) + | (Ediv_intnat, (x, (y, rest))) -> + logged_return ((Script_int.ediv x y, rest), ctxt) + | (Ediv_natint, (x, (y, rest))) -> + logged_return ((Script_int.ediv x y, rest), ctxt) + | (Ediv_natnat, (x, (y, rest))) -> + logged_return ((Script_int.ediv_n x y, rest), ctxt) + | (Lsl_nat, (x, (y, rest))) -> ( + match Script_int.shift_left_n x y with + | None -> + Log.get_log () >>=? fun log -> fail (Overflow (loc, log)) + | Some x -> + logged_return ((x, rest), ctxt) ) + | (Lsr_nat, (x, (y, rest))) -> ( + match Script_int.shift_right_n x y with + | None -> + Log.get_log () >>=? fun log -> fail (Overflow (loc, log)) + | Some r -> + logged_return ((r, rest), ctxt) ) + | (Or_nat, (x, (y, rest))) -> + logged_return ((Script_int.logor x y, rest), ctxt) + | (And_nat, (x, (y, rest))) -> + logged_return ((Script_int.logand x y, rest), ctxt) + | (And_int_nat, (x, (y, rest))) -> + logged_return ((Script_int.logand x y, rest), ctxt) + | (Xor_nat, (x, (y, rest))) -> + logged_return ((Script_int.logxor x y, rest), ctxt) + | (Not_int, (x, rest)) -> + logged_return ((Script_int.lognot x, rest), ctxt) + | (Not_nat, (x, rest)) -> + logged_return ((Script_int.lognot x, rest), ctxt) + (* control *) + | (Seq (hd, tl), stack) -> + non_terminal_recursion ~ctxt hd stack + >>=? fun (trans, ctxt) -> + step_bounded logger ~stack_depth ctxt step_constants tl trans + | (If (bt, _), (true, rest)) -> + step_bounded logger ~stack_depth ctxt step_constants bt rest + | (If (_, bf), (false, rest)) -> + step_bounded logger ~stack_depth ctxt step_constants bf rest + | (Loop body, (true, rest)) -> + non_terminal_recursion ~ctxt body rest + >>=? fun (trans, ctxt) -> + step_bounded logger ~stack_depth ctxt step_constants descr trans + | (Loop _, (false, rest)) -> + logged_return (rest, ctxt) + | (Loop_left body, (L v, rest)) -> + non_terminal_recursion ~ctxt body (v, rest) + >>=? fun (trans, ctxt) -> + step_bounded logger ~stack_depth ctxt step_constants descr trans + | (Loop_left _, (R v, rest)) -> + logged_return ((v, rest), ctxt) + | (Dip b, (ign, rest)) -> + non_terminal_recursion ~ctxt b rest + >>=? fun (res, ctxt) -> logged_return ((ign, res), ctxt) + | (Exec, (arg, (Lam (code, _), rest))) -> + Log.log_interp ctxt code (arg, ()) ; + non_terminal_recursion ~ctxt code (arg, ()) + >>=? fun ((res, ()), ctxt) -> logged_return ((res, rest), ctxt) + | (Apply capture_ty, (capture, (lam, rest))) -> ( + let (Lam (descr, expr)) = lam in + let (Item_t (full_arg_ty, _, _)) = descr.bef in + unparse_data ctxt Optimized capture_ty capture + >>=? fun (const_expr, ctxt) -> + unparse_ty ctxt capture_ty + >>?= fun (ty_expr, ctxt) -> + match full_arg_ty with + | Pair_t ((capture_ty, _, _), (arg_ty, _, _), _) -> + let arg_stack_ty = Item_t (arg_ty, Empty_t, None) in + let const_descr = + ( { + loc = descr.loc; + bef = arg_stack_ty; + aft = Item_t (capture_ty, arg_stack_ty, None); + instr = Const capture; + } + : (_, _) descr ) + in + let pair_descr = + ( { + loc = descr.loc; + bef = Item_t (capture_ty, arg_stack_ty, None); + aft = Item_t (full_arg_ty, Empty_t, None); + instr = Cons_pair; + } + : (_, _) descr ) + in + let seq_descr = + ( { + loc = descr.loc; + bef = arg_stack_ty; + aft = Item_t (full_arg_ty, Empty_t, None); + instr = Seq (const_descr, pair_descr); + } + : (_, _) descr ) + in + let full_descr = + ( { + loc = descr.loc; + bef = arg_stack_ty; + aft = descr.aft; + instr = Seq (seq_descr, descr); + } + : (_, _) descr ) + in + let full_expr = + Micheline.Seq + ( 0, + [ Prim (0, I_PUSH, [ty_expr; const_expr], []); + Prim (0, I_PAIR, [], []); + expr ] ) + in + let lam' = Lam (full_descr, full_expr) in + logged_return ((lam', rest), ctxt) + | _ -> + assert false ) + | (Lambda lam, rest) -> + logged_return ((lam, rest), ctxt) + | (Failwith tv, (v, _)) -> + trace Cannot_serialize_failure (unparse_data ctxt Optimized tv v) + >>=? fun (v, _ctxt) -> + let v = Micheline.strip_locations v in + Log.get_log () >>=? fun log -> fail (Reject (loc, v, log)) + | (Nop, stack) -> + logged_return (stack, ctxt) + (* comparison *) + | (Compare ty, (a, (b, rest))) -> + logged_return + ( ( Script_int.of_int @@ Script_ir_translator.compare_comparable ty a b, + rest ), + ctxt ) + (* comparators *) + | (Eq, (cmpres, rest)) -> + let cmpres = Script_int.compare cmpres Script_int.zero in + let cmpres = Compare.Int.(cmpres = 0) in + logged_return ((cmpres, rest), ctxt) + | (Neq, (cmpres, rest)) -> + let cmpres = Script_int.compare cmpres Script_int.zero in + let cmpres = Compare.Int.(cmpres <> 0) in + logged_return ((cmpres, rest), ctxt) + | (Lt, (cmpres, rest)) -> + let cmpres = Script_int.compare cmpres Script_int.zero in + let cmpres = Compare.Int.(cmpres < 0) in + logged_return ((cmpres, rest), ctxt) + | (Le, (cmpres, rest)) -> + let cmpres = Script_int.compare cmpres Script_int.zero in + let cmpres = Compare.Int.(cmpres <= 0) in + logged_return ((cmpres, rest), ctxt) + | (Gt, (cmpres, rest)) -> + let cmpres = Script_int.compare cmpres Script_int.zero in + let cmpres = Compare.Int.(cmpres > 0) in + logged_return ((cmpres, rest), ctxt) + | (Ge, (cmpres, rest)) -> + let cmpres = Script_int.compare cmpres Script_int.zero in + let cmpres = Compare.Int.(cmpres >= 0) in + logged_return ((cmpres, rest), ctxt) + (* packing *) + | (Pack t, (value, rest)) -> + Script_ir_translator.pack_data ctxt t value + >>=? fun (bytes, ctxt) -> logged_return ((bytes, rest), ctxt) + | (Unpack ty, (bytes, rest)) -> + unpack ctxt ~ty ~bytes + >>=? fun (opt, ctxt) -> logged_return ((opt, rest), ctxt) + (* protocol *) + | (Address, ((_, address), rest)) -> + logged_return ((address, rest), ctxt) + | (Contract (t, entrypoint), (contract, rest)) -> ( + match (contract, entrypoint) with + | ((contract, "default"), entrypoint) | ((contract, entrypoint), "default") + -> + Script_ir_translator.parse_contract_for_script + ctxt + loc + t + contract + ~entrypoint + >>=? fun (ctxt, maybe_contract) -> + logged_return ((maybe_contract, rest), ctxt) + | _ -> + logged_return ((None, rest), ctxt) ) + | (Transfer_tokens, (p, (amount, ((tp, (destination, entrypoint)), rest)))) + -> + collect_lazy_storage ctxt tp p + >>?= fun (to_duplicate, ctxt) -> + let to_update = no_lazy_storage_id in + extract_lazy_storage_diff + ctxt + Optimized + tp + p + ~to_duplicate + ~to_update + ~temporary:true + >>=? fun (p, lazy_storage_diff, ctxt) -> + unparse_data ctxt Optimized tp p + >>=? fun (p, ctxt) -> + Gas.consume ctxt (Script.strip_locations_cost p) + >>?= fun ctxt -> + let operation = + Transaction + { + amount; + destination; + entrypoint; + parameters = Script.lazy_expr (Micheline.strip_locations p); + } + in + fresh_internal_nonce ctxt + >>?= fun (ctxt, nonce) -> + logged_return + ( ( ( Internal_operation + {source = step_constants.self; operation; nonce}, + lazy_storage_diff ), + rest ), + ctxt ) + | (Implicit_account, (key, rest)) -> + let contract = Contract.implicit_contract key in + logged_return (((Unit_t None, (contract, "default")), rest), ctxt) + | ( Create_contract (storage_type, param_type, Lam (_, code), root_name), + (* Removed the instruction's arguments manager, spendable and delegatable *) + (delegate, (credit, (init, rest))) ) -> + unparse_ty ctxt param_type + >>?= fun (unparsed_param_type, ctxt) -> + let unparsed_param_type = + Script_ir_translator.add_field_annot root_name None unparsed_param_type + in + unparse_ty ctxt storage_type + >>?= fun (unparsed_storage_type, ctxt) -> + let code = + Micheline.strip_locations + (Seq + ( 0, + [ Prim (0, K_parameter, [unparsed_param_type], []); + Prim (0, K_storage, [unparsed_storage_type], []); + Prim (0, K_code, [code], []) ] )) + in + collect_lazy_storage ctxt storage_type init + >>?= fun (to_duplicate, ctxt) -> + let to_update = no_lazy_storage_id in + extract_lazy_storage_diff + ctxt + Optimized + storage_type + init + ~to_duplicate + ~to_update + ~temporary:true + >>=? fun (init, lazy_storage_diff, ctxt) -> + unparse_data ctxt Optimized storage_type init + >>=? fun (storage, ctxt) -> + Gas.consume ctxt (Script.strip_locations_cost storage) + >>?= fun ctxt -> + let storage = Micheline.strip_locations storage in + Contract.fresh_contract_from_current_nonce ctxt + >>?= fun (ctxt, contract) -> + let operation = + Origination + { + credit; + delegate; + preorigination = Some contract; + script = + { + code = Script.lazy_expr code; + storage = Script.lazy_expr storage; + }; + } + in + fresh_internal_nonce ctxt + >>?= fun (ctxt, nonce) -> + logged_return + ( ( ( Internal_operation + {source = step_constants.self; operation; nonce}, + lazy_storage_diff ), + ((contract, "default"), rest) ), + ctxt ) + | (Set_delegate, (delegate, rest)) -> + let operation = Delegation delegate in + fresh_internal_nonce ctxt + >>?= fun (ctxt, nonce) -> + logged_return + ( ( ( Internal_operation + {source = step_constants.self; operation; nonce}, + None ), + rest ), + ctxt ) + | (Balance, rest) -> + Contract.get_balance_carbonated ctxt step_constants.self + >>=? fun (ctxt, balance) -> logged_return ((balance, rest), ctxt) + | (Level, rest) -> + let level = + (Level.current ctxt).level |> Raw_level.to_int32 |> Script_int.of_int32 + |> Script_int.abs + in + logged_return ((level, rest), ctxt) + | (Now, rest) -> + let now = Script_timestamp.now ctxt in + logged_return ((now, rest), ctxt) + | (Check_signature, (key, (signature, (message, rest)))) -> + let res = Signature.check key signature message in + logged_return ((res, rest), ctxt) + | (Hash_key, (key, rest)) -> + logged_return ((Signature.Public_key.hash key, rest), ctxt) + | (Blake2b, (bytes, rest)) -> + let hash = Raw_hashes.blake2b bytes in + logged_return ((hash, rest), ctxt) + | (Sha256, (bytes, rest)) -> + let hash = Raw_hashes.sha256 bytes in + logged_return ((hash, rest), ctxt) + | (Sha512, (bytes, rest)) -> + let hash = Raw_hashes.sha512 bytes in + logged_return ((hash, rest), ctxt) + | (Source, rest) -> + logged_return (((step_constants.payer, "default"), rest), ctxt) + | (Sender, rest) -> + logged_return (((step_constants.source, "default"), rest), ctxt) + | (Self (t, entrypoint), rest) -> + logged_return (((t, (step_constants.self, entrypoint)), rest), ctxt) + | (Self_address, rest) -> + logged_return (((step_constants.self, "default"), rest), ctxt) + | (Amount, rest) -> + logged_return ((step_constants.amount, rest), ctxt) + | (Dig (_n, n'), stack) -> + interp_stack_prefix_preserving_operation + (fun (v, rest) -> return (rest, v)) + n' + stack + >>=? fun (aft, x) -> logged_return ((x, aft), ctxt) + | (Dug (_n, n'), (v, rest)) -> + interp_stack_prefix_preserving_operation + (fun stk -> return ((v, stk), ())) + n' + rest + >>=? fun (aft, ()) -> logged_return (aft, ctxt) + | (Dipn (n, n', b), stack) -> + interp_stack_prefix_preserving_operation + (fun stk -> + non_terminal_recursion + ~ctxt + b + stk + (* This is a cheap upper bound of the number recursive calls to + `interp_stack_prefix_preserving_operation`, which does + ((n / 16) + log2 (n % 16)) iterations *) + ~stack_depth:(stack_depth + 4 + (n / 16))) + n' + stack + >>=? fun (aft, ctxt') -> logged_return (aft, ctxt') + | (Dropn (_n, n'), stack) -> + interp_stack_prefix_preserving_operation + (fun stk -> return (stk, stk)) + n' + stack + >>=? fun (_, rest) -> logged_return (rest, ctxt) + | (Sapling_empty_state {memo_size}, stack) -> + logged_return ((Sapling.empty_state ~memo_size (), stack), ctxt) + | (Sapling_verify_update, (transaction, (state, rest))) -> ( + let address = Contract.to_b58check step_constants.self in + let chain_id = Chain_id.to_b58check step_constants.chain_id in + let anti_replay = address ^ chain_id in + Sapling.verify_update ctxt state transaction anti_replay + >>=? fun (ctxt, balance_state_opt) -> + match balance_state_opt with + | Some (balance, state) -> + logged_return + ((Some (Script_int.of_int64 balance, state), rest), ctxt) + | None -> + logged_return ((None, rest), ctxt) ) + | (ChainId, rest) -> + logged_return ((step_constants.chain_id, rest), ctxt) + | (Never, (_, _)) -> + . + | (Voting_power, (key_hash, rest)) -> + Vote.get_voting_power ctxt key_hash + >>=? fun (ctxt, rolls) -> + logged_return ((Script_int.(abs (of_int32 rolls)), rest), ctxt) + | (Total_voting_power, rest) -> + Vote.get_total_voting_power ctxt + >>=? fun (ctxt, rolls) -> + logged_return ((Script_int.(abs (of_int32 rolls)), rest), ctxt) + | (Keccak, (bytes, rest)) -> + let hash = Raw_hashes.keccak256 bytes in + logged_return ((hash, rest), ctxt) + | (Sha3, (bytes, rest)) -> + let hash = Raw_hashes.sha3_256 bytes in + logged_return ((hash, rest), ctxt) + | (Add_bls12_381_g1, (x, (y, rest))) -> + logged_return ((Bls12_381.G1.add x y, rest), ctxt) + | (Add_bls12_381_g2, (x, (y, rest))) -> + logged_return ((Bls12_381.G2.add x y, rest), ctxt) + | (Add_bls12_381_fr, (x, (y, rest))) -> + logged_return ((Bls12_381.Fr.add x y, rest), ctxt) + | (Mul_bls12_381_g1, (x, (y, rest))) -> + logged_return ((Bls12_381.G1.mul x y, rest), ctxt) + | (Mul_bls12_381_g2, (x, (y, rest))) -> + logged_return ((Bls12_381.G2.mul x y, rest), ctxt) + | (Mul_bls12_381_fr, (x, (y, rest))) -> + logged_return ((Bls12_381.Fr.mul x y, rest), ctxt) + | (Mul_bls12_381_fr_z, (x, (y, rest))) -> + let x = Bls12_381.Fr.of_z (Script_int.to_zint x) in + let res = (Bls12_381.Fr.mul x y, rest) in + logged_return (res, ctxt) + | (Mul_bls12_381_z_fr, (y, (x, rest))) -> + let x = Bls12_381.Fr.of_z (Script_int.to_zint x) in + let res = (Bls12_381.Fr.mul x y, rest) in + logged_return (res, ctxt) + | (Int_bls12_381_fr, (x, rest)) -> + logged_return ((Script_int.of_zint (Bls12_381.Fr.to_z x), rest), ctxt) + | (Neg_bls12_381_g1, (x, rest)) -> + logged_return ((Bls12_381.G1.negate x, rest), ctxt) + | (Neg_bls12_381_g2, (x, rest)) -> + logged_return ((Bls12_381.G2.negate x, rest), ctxt) + | (Neg_bls12_381_fr, (x, rest)) -> + logged_return ((Bls12_381.Fr.negate x, rest), ctxt) + | (Pairing_check_bls12_381, (pairs, rest)) -> + let check = + match pairs.elements with + | [] -> + true + | pairs -> + Bls12_381.( + miller_loop pairs |> final_exponentiation_opt + |> Option.map Gt.(eq one)) + |> Option.value ~default:false + in + logged_return ((check, rest), ctxt) + | (Comb (_, witness), stack) -> + let rec aux : + type before after. + (before, after) comb_gadt_witness -> before -> after = + fun witness stack -> + match (witness, stack) with + | (Comb_one, stack) -> + stack + | (Comb_succ witness', (a, tl)) -> + let (b, tl') = aux witness' tl in + ((a, b), tl') + in + logged_return (aux witness stack, ctxt) + | (Uncomb (_, witness), stack) -> + let rec aux : + type before after. + (before, after) uncomb_gadt_witness -> before -> after = + fun witness stack -> + match (witness, stack) with + | (Uncomb_one, stack) -> + stack + | (Uncomb_succ witness', ((a, b), tl)) -> + (a, aux witness' (b, tl)) + in + logged_return (aux witness stack, ctxt) + | (Comb_get (_, witness), (comb, stack)) -> + let rec aux : + type before after. + (before, after) comb_get_gadt_witness -> before -> after = + fun witness comb -> + match (witness, comb) with + | (Comb_get_zero, v) -> + v + | (Comb_get_one, (a, _)) -> + a + | (Comb_get_plus_two witness', (_, b)) -> + aux witness' b + in + logged_return ((aux witness comb, stack), ctxt) + | (Comb_set (_, witness), (value, (comb, stack))) -> + let rec aux : + type value before after. + (value, before, after) comb_set_gadt_witness -> + value -> + before -> + after = + fun witness value item -> + match (witness, item) with + | (Comb_set_zero, _) -> + value + | (Comb_set_one, (_hd, tl)) -> + (value, tl) + | (Comb_set_plus_two witness', (hd, tl)) -> + (hd, aux witness' value tl) + in + logged_return ((aux witness value comb, stack), ctxt) + | (Dup_n (_, witness), stack) -> + let rec aux : + type before after. + (before, after) dup_n_gadt_witness -> before -> after = + fun witness stack -> + match (witness, stack) with + | (Dup_n_zero, (a, _)) -> + a + | (Dup_n_succ witness', (_, tl)) -> + aux witness' tl + in + logged_return ((aux witness stack, stack), ctxt) + (* Tickets *) + | (Ticket, (contents, (amount, rest))) -> + let ticketer = (step_constants.self, "default") in + logged_return (({ticketer; contents; amount}, rest), ctxt) + | (Read_ticket, (({ticketer; contents; amount}, _) as stack)) -> + logged_return (((ticketer, (contents, amount)), stack), ctxt) + | (Split_ticket, (ticket, ((amount_a, amount_b), rest))) -> + let result = + if + Compare.Int.( + Script_int.(compare (add_n amount_a amount_b) ticket.amount) = 0) + then + Some + ({ticket with amount = amount_a}, {ticket with amount = amount_b}) + else None + in + logged_return ((result, rest), ctxt) + | (Join_tickets contents_ty, ((ticket_a, ticket_b), rest)) -> + let result = + if + Compare.Int.( + compare_address ticket_a.ticketer ticket_b.ticketer = 0 + && compare_comparable + contents_ty + ticket_a.contents + ticket_b.contents + = 0) + then + Some + { + ticketer = ticket_a.ticketer; + contents = ticket_a.contents; + amount = Script_int.add_n ticket_a.amount ticket_b.amount; + } + else None + in + logged_return ((result, rest), ctxt) + +let step : + type b a. + logger -> + context -> + step_constants -> + (b, a) descr -> + b -> + (a * context) tzresult Lwt.t = + step_bounded ~stack_depth:0 + +let interp : + type p r. + logger -> + context -> + step_constants -> + (p, r) lambda -> + p -> + (r * context) tzresult Lwt.t = + fun logger ctxt step_constants (Lam (code, _)) arg -> + let stack = (arg, ()) in + let module Log = (val logger) in + Log.log_interp ctxt code stack ; + step logger ctxt step_constants code stack + >|=? fun ((ret, ()), ctxt) -> (ret, ctxt) + +(* ---- contract handling ---------------------------------------------------*) +let execute logger ctxt mode step_constants ~entrypoint ~internal + unparsed_script arg : + ( Script.expr + * packed_internal_operation list + * context + * Lazy_storage.diffs option ) + tzresult + Lwt.t = + parse_script ctxt unparsed_script ~legacy:true ~allow_forged_in_storage:true + >>=? fun (Ex_script {code; arg_type; storage; storage_type; root_name}, ctxt) -> + record_trace + (Bad_contract_parameter step_constants.self) + (find_entrypoint arg_type ~root_name entrypoint) + >>?= fun (box, _) -> + trace + (Bad_contract_parameter step_constants.self) + (parse_data ctxt ~legacy:false ~allow_forged:internal arg_type (box arg)) + >>=? fun (arg, ctxt) -> + Script.force_decode_in_context ctxt unparsed_script.code + >>?= fun (script_code, ctxt) -> + Script_ir_translator.collect_lazy_storage ctxt arg_type arg + >>?= fun (to_duplicate, ctxt) -> + Script_ir_translator.collect_lazy_storage ctxt storage_type storage + >>?= fun (to_update, ctxt) -> + trace + (Runtime_contract_error (step_constants.self, script_code)) + (interp logger ctxt step_constants code (arg, storage)) + >>=? fun ((ops, storage), ctxt) -> + Script_ir_translator.extract_lazy_storage_diff + ctxt + mode + ~temporary:false + ~to_duplicate + ~to_update + storage_type + storage + >>=? fun (storage, lazy_storage_diff, ctxt) -> + trace + Cannot_serialize_storage + ( unparse_data ctxt mode storage_type storage + >>=? fun (storage, ctxt) -> + Lwt.return + ( Gas.consume ctxt (Script.strip_locations_cost storage) + >>? fun ctxt -> ok (Micheline.strip_locations storage, ctxt) ) ) + >|=? fun (storage, ctxt) -> + let (ops, op_diffs) = List.split ops.elements in + let lazy_storage_diff = + match + List.flatten + (List.map (Option.value ~default:[]) (op_diffs @ [lazy_storage_diff])) + with + | [] -> + None + | diff -> + Some diff + in + (storage, ops, ctxt, lazy_storage_diff) + +type execution_result = { + ctxt : context; + storage : Script.expr; + lazy_storage_diff : Lazy_storage.diffs option; + operations : packed_internal_operation list; +} + +let execute ?(logger = (module No_trace : STEP_LOGGER)) ctxt mode + step_constants ~script ~entrypoint ~parameter ~internal = + execute + logger + ctxt + mode + step_constants + ~entrypoint + ~internal + script + (Micheline.root parameter) + >|=? fun (storage, operations, ctxt, lazy_storage_diff) -> + {ctxt; storage; lazy_storage_diff; operations} diff --git a/src/proto_009_PsFLoren/lib_protocol/script_interpreter.mli b/src/proto_009_PsFLoren/lib_protocol/script_interpreter.mli new file mode 100644 index 0000000000000000000000000000000000000000..9d2f9147da7e837984e5d971f7f898eb0772c6f5 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_interpreter.mli @@ -0,0 +1,106 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type execution_trace = + (Script.location * Gas.t * (Script.expr * string option) list) list + +type error += + | Reject of Script.location * Script.expr * execution_trace option + +type error += Overflow of Script.location * execution_trace option + +type error += Runtime_contract_error : Contract.t * Script.expr -> error + +type error += Bad_contract_parameter of Contract.t (* `Permanent *) + +type error += Cannot_serialize_failure + +type error += Cannot_serialize_storage + +type error += Michelson_too_many_recursive_calls + +type execution_result = { + ctxt : context; + storage : Script.expr; + lazy_storage_diff : Lazy_storage.diffs option; + operations : packed_internal_operation list; +} + +type step_constants = { + source : Contract.t; + payer : Contract.t; + self : Contract.t; + amount : Tez.t; + chain_id : Chain_id.t; +} + +(** [STEP_LOGGER] is the module type of logging + modules as passed to the Michelson interpreter. + Note that logging must be performed by side-effects + on an underlying log structure. *) +module type STEP_LOGGER = sig + (** [log_interp] is called at each call of the internal + function [interp]. [interp] is called when starting + the interpretation of a script and subsequently + at each [Exec] instruction. *) + val log_interp : + context -> ('bef, 'aft) Script_typed_ir.descr -> 'bef -> unit + + (** [log_entry] is called {i before} executing + each instruction but {i after} gas for + this instruction has been successfully consumed. *) + val log_entry : context -> ('bef, 'aft) Script_typed_ir.descr -> 'bef -> unit + + (** [log_exit] is called {i after} executing each + instruction. *) + val log_exit : context -> ('bef, 'aft) Script_typed_ir.descr -> 'aft -> unit + + (** [get_log] allows to obtain an execution trace, if + any was produced. *) + val get_log : unit -> execution_trace option tzresult Lwt.t +end + +type logger = (module STEP_LOGGER) + +val step : + logger -> + context -> + step_constants -> + ('bef, 'aft) Script_typed_ir.descr -> + 'bef -> + ('aft * context) tzresult Lwt.t + +val execute : + ?logger:logger -> + Alpha_context.t -> + Script_ir_translator.unparsing_mode -> + step_constants -> + script:Script.t -> + entrypoint:string -> + parameter:Script.expr -> + internal:bool -> + execution_result tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/script_ir_annot.ml b/src/proto_009_PsFLoren/lib_protocol/script_ir_annot.ml new file mode 100644 index 0000000000000000000000000000000000000000..0b1080ecad2c57b7e07458d5304ec95484559a45 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_ir_annot.ml @@ -0,0 +1,608 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Micheline +open Script_tc_errors +open Script_typed_ir + +let default_now_annot = Some (Var_annot "now") + +let default_amount_annot = Some (Var_annot "amount") + +let default_balance_annot = Some (Var_annot "balance") + +let default_level_annot = Some (Var_annot "level") + +let default_steps_annot = Some (Var_annot "steps") + +let default_source_annot = Some (Var_annot "source") + +let default_sender_annot = Some (Var_annot "sender") + +let default_self_annot = Some (Var_annot "self") + +let default_arg_annot = Some (Var_annot "arg") + +let default_param_annot = Some (Var_annot "parameter") + +let default_storage_annot = Some (Var_annot "storage") + +let default_car_annot = Some (Field_annot "car") + +let default_cdr_annot = Some (Field_annot "cdr") + +let default_contract_annot = Some (Field_annot "contract") + +let default_addr_annot = Some (Field_annot "address") + +let default_manager_annot = Some (Field_annot "manager") + +let default_pack_annot = Some (Field_annot "packed") + +let default_unpack_annot = Some (Field_annot "unpacked") + +let default_slice_annot = Some (Field_annot "slice") + +let default_elt_annot = Some (Field_annot "elt") + +let default_key_annot = Some (Field_annot "key") + +let default_hd_annot = Some (Field_annot "hd") + +let default_tl_annot = Some (Field_annot "tl") + +let default_some_annot = Some (Field_annot "some") + +let default_left_annot = Some (Field_annot "left") + +let default_right_annot = Some (Field_annot "right") + +let default_binding_annot = Some (Field_annot "bnd") + +let default_sapling_state_annot = Some (Var_annot "sapling") + +let default_sapling_balance_annot = Some (Var_annot "sapling_balance") + +let unparse_type_annot : type_annot option -> string list = function + | None -> + [] + | Some (Type_annot a) -> + [":" ^ a] + +let unparse_var_annot : var_annot option -> string list = function + | None -> + [] + | Some (Var_annot a) -> + ["@" ^ a] + +let unparse_field_annot : field_annot option -> string list = function + | None -> + [] + | Some (Field_annot a) -> + ["%" ^ a] + +let field_to_var_annot : field_annot option -> var_annot option = function + | None -> + None + | Some (Field_annot s) -> + Some (Var_annot s) + +let type_to_var_annot : type_annot option -> var_annot option = function + | None -> + None + | Some (Type_annot s) -> + Some (Var_annot s) + +let var_to_field_annot : var_annot option -> field_annot option = function + | None -> + None + | Some (Var_annot s) -> + Some (Field_annot s) + +let default_annot ~default = function None -> default | annot -> annot + +let gen_access_annot : + var_annot option -> + ?default:field_annot option -> + field_annot option -> + var_annot option = + fun value_annot ?(default = None) field_annot -> + match (value_annot, field_annot, default) with + | (None, None, _) | (Some _, None, None) | (None, Some (Field_annot ""), _) + -> + None + | (None, Some (Field_annot f), _) -> + Some (Var_annot f) + | (Some (Var_annot v), (None | Some (Field_annot "")), Some (Field_annot f)) + -> + Some (Var_annot (String.concat "." [v; f])) + | (Some (Var_annot v), Some (Field_annot f), _) -> + Some (Var_annot (String.concat "." [v; f])) + +let merge_type_annot : + legacy:bool -> + type_annot option -> + type_annot option -> + type_annot option tzresult = + fun ~legacy annot1 annot2 -> + match (annot1, annot2) with + | (None, None) | (Some _, None) | (None, Some _) -> + ok_none + | (Some (Type_annot a1), Some (Type_annot a2)) -> + if legacy || String.equal a1 a2 then ok annot1 + else error (Inconsistent_annotations (":" ^ a1, ":" ^ a2)) + +let merge_field_annot : + legacy:bool -> + field_annot option -> + field_annot option -> + field_annot option tzresult = + fun ~legacy annot1 annot2 -> + match (annot1, annot2) with + | (None, None) | (Some _, None) | (None, Some _) -> + ok_none + | (Some (Field_annot a1), Some (Field_annot a2)) -> + if legacy || String.equal a1 a2 then ok annot1 + else error (Inconsistent_annotations ("%" ^ a1, "%" ^ a2)) + +let merge_var_annot : var_annot option -> var_annot option -> var_annot option + = + fun annot1 annot2 -> + match (annot1, annot2) with + | (None, None) | (Some _, None) | (None, Some _) -> + None + | (Some (Var_annot a1), Some (Var_annot a2)) -> + if String.equal a1 a2 then annot1 else None + +let error_unexpected_annot loc annot = + match annot with + | [] -> + ok_unit + | _ :: _ -> + error (Unexpected_annotation loc) + +(* Check that the predicate p holds on all s.[k] for k >= i *) +let string_iter p s i = + let len = String.length s in + let rec aux i = + if Compare.Int.(i >= len) then ok_unit + else p s.[i] >>? fun () -> aux (i + 1) + in + aux i + +(* Valid annotation characters as defined by the allowed_annot_char function from lib_micheline/micheline_parser *) +let check_char loc = function + | 'a' .. 'z' | 'A' .. 'Z' | '_' | '.' | '%' | '@' | '0' .. '9' -> + ok_unit + | _ -> + error (Unexpected_annotation loc) + +(* This constant is defined in lib_micheline/micheline_parser which is not available in the environment. *) +let max_annot_length = 255 + +type annot_opt = + | Field_annot_opt of string option + | Type_annot_opt of string option + | Var_annot_opt of string option + +let parse_annots loc ?(allow_special_var = false) + ?(allow_special_field = false) l = + (* allow empty annotations as wildcards but otherwise only accept + annotations that start with [a-zA-Z_] *) + let sub_or_wildcard ~specials wrap s acc = + let mem_char c cs = List.exists (Char.equal c) cs in + let len = String.length s in + ( if Compare.Int.(len > max_annot_length) then + error (Unexpected_annotation loc) + else ok_unit ) + >>? fun () -> + if Compare.Int.(len = 1) then ok @@ (wrap None :: acc) + else + match s.[1] with + | 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' -> + (* check that all characters are valid*) + string_iter (check_char loc) s 2 + >>? fun () -> ok @@ (wrap (Some (String.sub s 1 (len - 1))) :: acc) + | '@' when Compare.Int.(len = 2) && mem_char '@' specials -> + ok @@ (wrap (Some "@") :: acc) + | '%' when mem_char '%' specials -> + if Compare.Int.(len = 2) then ok @@ (wrap (Some "%") :: acc) + else if Compare.Int.(len = 3) && Compare.Char.(s.[2] = '%') then + ok @@ (wrap (Some "%%") :: acc) + else error (Unexpected_annotation loc) + | _ -> + error (Unexpected_annotation loc) + in + List.fold_left + (fun acc s -> + acc + >>? fun acc -> + if Compare.Int.(String.length s = 0) then + error (Unexpected_annotation loc) + else + match s.[0] with + | ':' -> + sub_or_wildcard ~specials:[] (fun a -> Type_annot_opt a) s acc + | '@' -> + sub_or_wildcard + ~specials:(if allow_special_var then ['%'] else []) + (fun a -> Var_annot_opt a) + s + acc + | '%' -> + sub_or_wildcard + ~specials:(if allow_special_field then ['@'] else []) + (fun a -> Field_annot_opt a) + s + acc + | _ -> + error (Unexpected_annotation loc)) + ok_nil + l + >|? List.rev + +let opt_var_of_var_opt = function None -> None | Some a -> Some (Var_annot a) + +let opt_field_of_field_opt = function + | None -> + None + | Some a -> + Some (Field_annot a) + +let opt_type_of_type_opt = function + | None -> + None + | Some a -> + Some (Type_annot a) + +let classify_annot loc l : + (var_annot option list * type_annot option list * field_annot option list) + tzresult = + try + let (_, rv, _, rt, _, rf) = + List.fold_left + (fun (in_v, rv, in_t, rt, in_f, rf) a -> + match (a, in_v, rv, in_t, rt, in_f, rf) with + | (Var_annot_opt a, true, _, _, _, _, _) + | (Var_annot_opt a, false, [], _, _, _, _) -> + (true, opt_var_of_var_opt a :: rv, false, rt, false, rf) + | (Type_annot_opt a, _, _, true, _, _, _) + | (Type_annot_opt a, _, _, false, [], _, _) -> + (false, rv, true, opt_type_of_type_opt a :: rt, false, rf) + | (Field_annot_opt a, _, _, _, _, true, _) + | (Field_annot_opt a, _, _, _, _, false, []) -> + (false, rv, false, rt, true, opt_field_of_field_opt a :: rf) + | _ -> + raise Exit) + (false, [], false, [], false, []) + l + in + ok (List.rev rv, List.rev rt, List.rev rf) + with Exit -> error (Ungrouped_annotations loc) + +let get_one_annot loc = function + | [] -> + ok_none + | [a] -> + ok a + | _ -> + error (Unexpected_annotation loc) + +let get_two_annot loc = function + | [] -> + ok (None, None) + | [a] -> + ok (a, None) + | [a; b] -> + ok (a, b) + | _ -> + error (Unexpected_annotation loc) + +let parse_type_annot : int -> string list -> type_annot option tzresult = + fun loc annot -> + parse_annots loc annot >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc vars + >>? fun () -> + error_unexpected_annot loc fields >>? fun () -> get_one_annot loc types + +let parse_type_field_annot : + int -> string list -> (type_annot option * field_annot option) tzresult = + fun loc annot -> + parse_annots loc annot >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc vars + >>? fun () -> + get_one_annot loc types + >>? fun t -> get_one_annot loc fields >|? fun f -> (t, f) + +let parse_composed_type_annot : + int -> + string list -> + (type_annot option * field_annot option * field_annot option) tzresult = + fun loc annot -> + parse_annots loc annot >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc vars + >>? fun () -> + get_one_annot loc types + >>? fun t -> get_two_annot loc fields >|? fun (f1, f2) -> (t, f1, f2) + +let parse_field_annot : int -> string list -> field_annot option tzresult = + fun loc annot -> + parse_annots loc annot >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc vars + >>? fun () -> + error_unexpected_annot loc types >>? fun () -> get_one_annot loc fields + +let extract_field_annot : + Script.node -> (Script.node * field_annot option) tzresult = function + | Prim (loc, prim, args, annot) -> + let rec extract_first acc = function + | [] -> + (None, annot) + | s :: rest -> + if Compare.Int.(String.length s > 0) && Compare.Char.(s.[0] = '%') + then (Some s, List.rev_append acc rest) + else extract_first (s :: acc) rest + in + let (field_annot, annot) = extract_first [] annot in + ( match field_annot with + | None -> + ok_none + | Some field_annot -> + parse_field_annot loc [field_annot] ) + >|? fun field_annot -> (Prim (loc, prim, args, annot), field_annot) + | expr -> + ok (expr, None) + +let check_correct_field : + field_annot option -> field_annot option -> unit tzresult = + fun f1 f2 -> + match (f1, f2) with + | (None, _) | (_, None) -> + ok_unit + | (Some (Field_annot s1), Some (Field_annot s2)) -> + if String.equal s1 s2 then ok_unit + else error (Inconsistent_field_annotations ("%" ^ s1, "%" ^ s2)) + +let parse_var_annot : + int -> + ?default:var_annot option -> + string list -> + var_annot option tzresult = + fun loc ?default annot -> + parse_annots loc annot >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc types + >>? fun () -> + error_unexpected_annot loc fields + >>? fun () -> + get_one_annot loc vars + >|? function + | Some _ as a -> + a + | None -> ( + match default with Some a -> a | None -> None ) + +let split_last_dot = function + | None -> + (None, None) + | Some (Field_annot s) -> ( + match String.rindex_opt s '.' with + | None -> + (None, Some (Field_annot s)) + | Some i -> + let s1 = String.sub s 0 i in + let s2 = String.sub s (i + 1) (String.length s - i - 1) in + let f = + if Compare.String.equal s2 "car" || Compare.String.equal s2 "cdr" + then None + else Some (Field_annot s2) + in + (Some (Var_annot s1), f) ) + +let common_prefix v1 v2 = + match (v1, v2) with + | (Some (Var_annot s1), Some (Var_annot s2)) when Compare.String.equal s1 s2 + -> + v1 + | (Some _, None) -> + v1 + | (None, Some _) -> + v2 + | (_, _) -> + None + +let parse_constr_annot : + int -> + ?if_special_first:field_annot option -> + ?if_special_second:field_annot option -> + string list -> + ( var_annot option + * type_annot option + * field_annot option + * field_annot option ) + tzresult = + fun loc ?if_special_first ?if_special_second annot -> + parse_annots ~allow_special_field:true loc annot + >>? classify_annot loc + >>? fun (vars, types, fields) -> + get_one_annot loc vars + >>? fun v -> + get_one_annot loc types + >>? fun t -> + get_two_annot loc fields + >>? fun (f1, f2) -> + ( match (if_special_first, f1) with + | (Some special_var, Some (Field_annot "@")) -> + ok (split_last_dot special_var) + | (None, Some (Field_annot "@")) -> + error (Unexpected_annotation loc) + | (_, _) -> + ok (v, f1) ) + >>? fun (v1, f1) -> + ( match (if_special_second, f2) with + | (Some special_var, Some (Field_annot "@")) -> + ok (split_last_dot special_var) + | (None, Some (Field_annot "@")) -> + error (Unexpected_annotation loc) + | (_, _) -> + ok (v, f2) ) + >|? fun (v2, f2) -> + let v = match v with None -> common_prefix v1 v2 | Some _ -> v in + (v, t, f1, f2) + +let parse_two_var_annot : + int -> string list -> (var_annot option * var_annot option) tzresult = + fun loc annot -> + parse_annots loc annot >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc types + >>? fun () -> + error_unexpected_annot loc fields >>? fun () -> get_two_annot loc vars + +let var_annot_from_special : + field_name:field_annot option -> + default:var_annot option -> + value_annot:var_annot option -> + var_annot option -> + var_annot option = + fun ~field_name ~default ~value_annot v -> + match v with + | Some (Var_annot "%") -> + field_to_var_annot field_name + | Some (Var_annot "%%") -> + default + | Some _ -> + v + | None -> + value_annot + +let parse_destr_annot : + int -> + string list -> + default_accessor:field_annot option -> + field_name:field_annot option -> + pair_annot:var_annot option -> + value_annot:var_annot option -> + (var_annot option * field_annot option) tzresult = + fun loc annot ~default_accessor ~field_name ~pair_annot ~value_annot -> + parse_annots loc ~allow_special_var:true annot + >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc types + >>? fun () -> + get_one_annot loc vars + >>? fun v -> + get_one_annot loc fields + >|? fun f -> + let default = + gen_access_annot pair_annot field_name ~default:default_accessor + in + let v = var_annot_from_special ~field_name ~default ~value_annot v in + (v, f) + +let parse_unpair_annot : + int -> + string list -> + field_name_car:field_annot option -> + field_name_cdr:field_annot option -> + pair_annot:var_annot option -> + value_annot_car:var_annot option -> + value_annot_cdr:var_annot option -> + ( var_annot option + * var_annot option + * field_annot option + * field_annot option ) + tzresult = + fun loc + annot + ~field_name_car + ~field_name_cdr + ~pair_annot + ~value_annot_car + ~value_annot_cdr -> + parse_annots loc ~allow_special_var:true annot + >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc types + >>? fun () -> + get_two_annot loc vars + >>? fun (vcar, vcdr) -> + get_two_annot loc fields + >|? fun (fcar, fcdr) -> + let default_car = + gen_access_annot pair_annot field_name_car ~default:default_car_annot + in + let default_cdr = + gen_access_annot pair_annot field_name_cdr ~default:default_cdr_annot + in + let vcar = + var_annot_from_special + ~field_name:field_name_car + ~default:default_car + ~value_annot:value_annot_car + vcar + in + let vcdr = + var_annot_from_special + ~field_name:field_name_cdr + ~default:default_cdr + ~value_annot:value_annot_cdr + vcdr + in + (vcar, vcdr, fcar, fcdr) + +let parse_entrypoint_annot : + int -> + ?default:var_annot option -> + string list -> + (var_annot option * field_annot option) tzresult = + fun loc ?default annot -> + parse_annots loc annot >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc types + >>? fun () -> + get_one_annot loc fields + >>? fun f -> + get_one_annot loc vars + >|? function + | Some _ as a -> + (a, f) + | None -> ( + match default with Some a -> (a, f) | None -> (None, f) ) + +let parse_var_type_annot : + int -> string list -> (var_annot option * type_annot option) tzresult = + fun loc annot -> + parse_annots loc annot >>? classify_annot loc + >>? fun (vars, types, fields) -> + error_unexpected_annot loc fields + >>? fun () -> + get_one_annot loc vars + >>? fun v -> get_one_annot loc types >|? fun t -> (v, t) diff --git a/src/proto_009_PsFLoren/lib_protocol/script_ir_annot.mli b/src/proto_009_PsFLoren/lib_protocol/script_ir_annot.mli new file mode 100644 index 0000000000000000000000000000000000000000..1fd5bf59693359ee9e1cfdc7b2877014d0070e75 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_ir_annot.mli @@ -0,0 +1,215 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script_typed_ir + +(** Default annotations *) + +val default_now_annot : var_annot option + +val default_amount_annot : var_annot option + +val default_balance_annot : var_annot option + +val default_level_annot : var_annot option + +val default_steps_annot : var_annot option + +val default_source_annot : var_annot option + +val default_sender_annot : var_annot option + +val default_self_annot : var_annot option + +val default_arg_annot : var_annot option + +val default_param_annot : var_annot option + +val default_storage_annot : var_annot option + +val default_sapling_state_annot : var_annot option + +val default_sapling_balance_annot : var_annot option + +val default_car_annot : field_annot option + +val default_cdr_annot : field_annot option + +val default_contract_annot : field_annot option + +val default_addr_annot : field_annot option + +val default_manager_annot : field_annot option + +val default_pack_annot : field_annot option + +val default_unpack_annot : field_annot option + +val default_slice_annot : field_annot option + +val default_elt_annot : field_annot option + +val default_key_annot : field_annot option + +val default_hd_annot : field_annot option + +val default_tl_annot : field_annot option + +val default_some_annot : field_annot option + +val default_left_annot : field_annot option + +val default_right_annot : field_annot option + +val default_binding_annot : field_annot option + +(** Unparse annotations to their string representation *) + +val unparse_type_annot : type_annot option -> string list + +val unparse_var_annot : var_annot option -> string list + +val unparse_field_annot : field_annot option -> string list + +(** Conversion functions between different annotation kinds *) + +val field_to_var_annot : field_annot option -> var_annot option + +val type_to_var_annot : type_annot option -> var_annot option + +val var_to_field_annot : var_annot option -> field_annot option + +(** Replace an annotation by its default value if it is [None] *) +val default_annot : default:'a option -> 'a option -> 'a option + +(** Generate annotation for field accesses, of the form [var.field1.field2] *) +val gen_access_annot : + var_annot option -> + ?default:field_annot option -> + field_annot option -> + var_annot option + +(** Merge type annotations. + @return an error {!Inconsistent_type_annotations} if they are both present + and different, unless [legacy] *) +val merge_type_annot : + legacy:bool -> + type_annot option -> + type_annot option -> + type_annot option tzresult + +(** Merge field annotations. + @return an error {!Inconsistent_type_annotations} if they are both present + and different, unless [legacy] *) +val merge_field_annot : + legacy:bool -> + field_annot option -> + field_annot option -> + field_annot option tzresult + +(** Merge variable annotations, does not fail ([None] if different). *) +val merge_var_annot : var_annot option -> var_annot option -> var_annot option + +(** @return an error {!Unexpected_annotation} in the monad the list is not empty. *) +val error_unexpected_annot : int -> 'a list -> unit tzresult + +(** Parse a type annotation only. *) +val parse_type_annot : int -> string list -> type_annot option tzresult + +(** Parse a field annotation only. *) +val parse_field_annot : int -> string list -> field_annot option tzresult + +(** Parse an annotation for composed types, of the form + [:ty_name %field] in any order. *) +val parse_type_field_annot : + int -> string list -> (type_annot option * field_annot option) tzresult + +(** Parse an annotation for composed types, of the form + [:ty_name %field1 %field2] in any order. *) +val parse_composed_type_annot : + int -> + string list -> + (type_annot option * field_annot option * field_annot option) tzresult + +(** Extract and remove a field annotation from a node *) +val extract_field_annot : + Script.node -> (Script.node * field_annot option) tzresult + +(** Check that field annotations match, used for field accesses. *) +val check_correct_field : + field_annot option -> field_annot option -> unit tzresult + +(** Instruction annotations parsing *) + +(** Parse a variable annotation, replaced by a default value if [None]. *) +val parse_var_annot : + int -> ?default:var_annot option -> string list -> var_annot option tzresult + +val parse_constr_annot : + int -> + ?if_special_first:field_annot option -> + ?if_special_second:field_annot option -> + string list -> + ( var_annot option + * type_annot option + * field_annot option + * field_annot option ) + tzresult + +val parse_two_var_annot : + int -> string list -> (var_annot option * var_annot option) tzresult + +val parse_destr_annot : + int -> + string list -> + default_accessor:field_annot option -> + field_name:field_annot option -> + pair_annot:var_annot option -> + value_annot:var_annot option -> + (var_annot option * field_annot option) tzresult + +val parse_unpair_annot : + int -> + string list -> + field_name_car:field_annot option -> + field_name_cdr:field_annot option -> + pair_annot:var_annot option -> + value_annot_car:var_annot option -> + value_annot_cdr:var_annot option -> + ( var_annot option + * var_annot option + * field_annot option + * field_annot option ) + tzresult + +val parse_entrypoint_annot : + int -> + ?default:var_annot option -> + string list -> + (var_annot option * field_annot option) tzresult + +val parse_var_type_annot : + int -> string list -> (var_annot option * type_annot option) tzresult diff --git a/src/proto_009_PsFLoren/lib_protocol/script_ir_translator.ml b/src/proto_009_PsFLoren/lib_protocol/script_ir_translator.ml new file mode 100644 index 0000000000000000000000000000000000000000..0f95179af3747f72a40e9887c89ad27dafd1092f --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_ir_translator.ml @@ -0,0 +1,7423 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Micheline +open Script +open Script_typed_ir +open Script_tc_errors +open Script_ir_annot +module Typecheck_costs = Michelson_v1_gas.Cost_of.Typechecking +module Unparse_costs = Michelson_v1_gas.Cost_of.Unparsing + +type ex_comparable_ty = + | Ex_comparable_ty : 'a comparable_ty -> ex_comparable_ty + +type ex_ty = Ex_ty : 'a ty -> ex_ty + +type ex_stack_ty = Ex_stack_ty : 'a stack_ty -> ex_stack_ty + +type tc_context = + | Lambda : tc_context + | Dip : 'a stack_ty * tc_context -> tc_context + | Toplevel : { + storage_type : 'sto ty; + param_type : 'param ty; + root_name : field_annot option; + legacy_create_contract_literal : bool; + } + -> tc_context + +type unparsing_mode = Optimized | Readable | Optimized_legacy + +type type_logger = + int -> + (Script.expr * Script.annot) list -> + (Script.expr * Script.annot) list -> + unit + +let add_dip ty annot prev = + match prev with + | Lambda | Toplevel _ -> + Dip (Item_t (ty, Empty_t, annot), prev) + | Dip (stack, _) -> + Dip (Item_t (ty, stack, annot), prev) + +(* ---- Type size accounting ------------------------------------------------*) + +let rec comparable_type_size : type t. t comparable_ty -> int = + fun ty -> + (* No wildcard to force the update when comparable_ty changes. *) + match ty with + | Unit_key _ -> + 1 + | Never_key _ -> + 1 + | Int_key _ -> + 1 + | Nat_key _ -> + 1 + | Signature_key _ -> + 1 + | String_key _ -> + 1 + | Bytes_key _ -> + 1 + | Mutez_key _ -> + 1 + | Bool_key _ -> + 1 + | Key_hash_key _ -> + 1 + | Key_key _ -> + 1 + | Timestamp_key _ -> + 1 + | Chain_id_key _ -> + 1 + | Address_key _ -> + 1 + | Pair_key ((t1, _), (t2, _), _) -> + 1 + comparable_type_size t1 + comparable_type_size t2 + | Union_key ((t1, _), (t2, _), _) -> + 1 + comparable_type_size t1 + comparable_type_size t2 + | Option_key (t, _) -> + 1 + comparable_type_size t + +let rec type_size : type t. t ty -> int = + fun ty -> + match ty with + | Unit_t _ -> + 1 + | Int_t _ -> + 1 + | Nat_t _ -> + 1 + | Signature_t _ -> + 1 + | Bytes_t _ -> + 1 + | String_t _ -> + 1 + | Mutez_t _ -> + 1 + | Key_hash_t _ -> + 1 + | Key_t _ -> + 1 + | Timestamp_t _ -> + 1 + | Address_t _ -> + 1 + | Bool_t _ -> + 1 + | Operation_t _ -> + 1 + | Chain_id_t _ -> + 1 + | Never_t _ -> + 1 + | Bls12_381_g1_t _ -> + 1 + | Bls12_381_g2_t _ -> + 1 + | Bls12_381_fr_t _ -> + 1 + | Sapling_transaction_t _ -> + 1 + | Sapling_state_t _ -> + 1 + | Pair_t ((l, _, _), (r, _, _), _) -> + 1 + type_size l + type_size r + | Union_t ((l, _), (r, _), _) -> + 1 + type_size l + type_size r + | Lambda_t (arg, ret, _) -> + 1 + type_size arg + type_size ret + | Option_t (t, _) -> + 1 + type_size t + | List_t (t, _) -> + 1 + type_size t + | Ticket_t (t, _) -> + 1 + comparable_type_size t + | Set_t (k, _) -> + 1 + comparable_type_size k + | Map_t (k, v, _) -> + 1 + comparable_type_size k + type_size v + | Big_map_t (k, v, _) -> + 1 + comparable_type_size k + type_size v + | Contract_t (arg, _) -> + 1 + type_size arg + +let rec type_size_of_stack_head : type st. st stack_ty -> up_to:int -> int = + fun stack ~up_to -> + match stack with + | Empty_t -> + 0 + | Item_t (head, tail, _annot) -> + if Compare.Int.(up_to > 0) then + Compare.Int.max + (type_size head) + (type_size_of_stack_head tail ~up_to:(up_to - 1)) + else 0 + +(* This is the depth of the stack to inspect for sizes overflow. We + only need to check the produced types that can be larger than the + arguments. That's why Swap is 0 for instance as no type grows. + Constant sized types are not checked: it is assumed they are lower + than the bound (otherwise every program would be rejected). + + In a [(b, a) instr], it is the number of types in [a] that may exceed the + limit, knowing that types in [b] don't. + If the instr is parameterized by [(b', a') descr] then you may assume that + types in [a'] don't exceed the limit. +*) +let number_of_generated_growing_types : type b a. (b, a) instr -> int = + function + (* Constructors *) + | Const _ -> + 1 + | Cons_pair -> + 1 + | Cons_some -> + 1 + | Cons_none _ -> + 1 + | Cons_left -> + 1 + | Cons_right -> + 1 + | Nil -> + 1 + | Empty_set _ -> + 1 + | Empty_map _ -> + 1 + | Empty_big_map _ -> + 1 + | Lambda _ -> + 1 + | Self _ -> + 1 + | Contract _ -> + 1 + | Ticket -> + 1 + | Read_ticket -> + (* `pair address (pair T nat)` is bigger than `ticket T` *) + 1 + | Split_ticket -> + 1 + (* Magic constructor *) + | Unpack _ -> + 1 + (* Mappings *) + | List_map _ -> + 1 + | Map_map _ -> + 1 + (* Others: + - don't add types + - don't change types + - decrease type sizes + - produce only constants + - have types bounded by parameters + - etc. *) + | Drop -> + 0 + | Dup -> + 0 + | Swap -> + 0 + | Unpair -> + 0 + | Car -> + 0 + | Cdr -> + 0 + | If_none _ -> + 0 + | If_left _ -> + 0 + | Cons_list -> + 0 + | If_cons _ -> + 0 + | List_size -> + 0 + | List_iter _ -> + 0 + | Set_iter _ -> + 0 + | Set_mem -> + 0 + | Set_update -> + 0 + | Set_size -> + 0 + | Map_iter _ -> + 0 + | Map_mem -> + 0 + | Map_get -> + 0 + | Map_update -> + 0 + | Map_get_and_update -> + 0 + | Map_size -> + 0 + | Big_map_get -> + 0 + | Big_map_update -> + 0 + | Big_map_get_and_update -> + 0 + | Big_map_mem -> + 0 + | Concat_string -> + 0 + | Concat_string_pair -> + 0 + | Slice_string -> + 0 + | String_size -> + 0 + | Concat_bytes -> + 0 + | Concat_bytes_pair -> + 0 + | Slice_bytes -> + 0 + | Bytes_size -> + 0 + | Add_seconds_to_timestamp -> + 0 + | Add_timestamp_to_seconds -> + 0 + | Sub_timestamp_seconds -> + 0 + | Diff_timestamps -> + 0 + | Add_tez -> + 0 + | Sub_tez -> + 0 + | Mul_teznat -> + 0 + | Mul_nattez -> + 0 + | Ediv_teznat -> + 0 + | Ediv_tez -> + 0 + | Or -> + 0 + | And -> + 0 + | Xor -> + 0 + | Not -> + 0 + | Is_nat -> + 0 + | Neg_nat -> + 0 + | Neg_int -> + 0 + | Abs_int -> + 0 + | Int_nat -> + 0 + | Add_intint -> + 0 + | Add_intnat -> + 0 + | Add_natint -> + 0 + | Add_natnat -> + 0 + | Sub_int -> + 0 + | Mul_intint -> + 0 + | Mul_intnat -> + 0 + | Mul_natint -> + 0 + | Mul_natnat -> + 0 + | Ediv_intint -> + 0 + | Ediv_intnat -> + 0 + | Ediv_natint -> + 0 + | Ediv_natnat -> + 0 + | Lsl_nat -> + 0 + | Lsr_nat -> + 0 + | Or_nat -> + 0 + | And_nat -> + 0 + | And_int_nat -> + 0 + | Xor_nat -> + 0 + | Not_nat -> + 0 + | Not_int -> + 0 + | Seq _ -> + 0 + | If _ -> + 0 + | Loop _ -> + 0 + | Loop_left _ -> + 0 + | Dip _ -> + 0 + | Exec -> + 0 + | Apply _ -> + 0 + | Failwith _ -> + 0 + | Nop -> + 0 + | Compare _ -> + 0 + | Eq -> + 0 + | Neq -> + 0 + | Lt -> + 0 + | Gt -> + 0 + | Le -> + 0 + | Ge -> + 0 + | Address -> + 0 + | Transfer_tokens -> + 0 + | Implicit_account -> + 0 + | Create_contract _ -> + 0 + | Now -> + 0 + | Level -> + 0 + | Balance -> + 0 + | Check_signature -> + 0 + | Hash_key -> + 0 + | Blake2b -> + 0 + | Sha256 -> + 0 + | Sha512 -> + 0 + | Source -> + 0 + | Sender -> + 0 + | Amount -> + 0 + | Self_address -> + 0 + | Sapling_empty_state _ -> + 0 + | Sapling_verify_update -> + 0 + | Set_delegate -> + 0 + | Pack _ -> + 0 + | Dig _ -> + 0 + | Dug _ -> + 0 + | Dipn _ -> + 0 + | Dropn _ -> + 0 + | ChainId -> + 0 + | Never -> + 0 + | Voting_power -> + 0 + | Total_voting_power -> + 0 + | Keccak -> + 0 + | Sha3 -> + 0 + | Add_bls12_381_g1 -> + 0 + | Add_bls12_381_g2 -> + 0 + | Add_bls12_381_fr -> + 0 + | Mul_bls12_381_g1 -> + 0 + | Mul_bls12_381_g2 -> + 0 + | Mul_bls12_381_fr -> + 0 + | Mul_bls12_381_fr_z -> + 0 + | Mul_bls12_381_z_fr -> + 0 + | Int_bls12_381_fr -> + 0 + | Neg_bls12_381_g1 -> + 0 + | Neg_bls12_381_g2 -> + 0 + | Neg_bls12_381_fr -> + 0 + | Pairing_check_bls12_381 -> + 0 + | Uncomb _ -> + 0 + | Comb_get _ -> + 0 + | Comb _ -> + 1 + | Comb_set _ -> + 1 + | Dup_n _ -> + 0 + | Join_tickets _ -> + 0 + +(* ---- Error helpers -------------------------------------------------------*) + +let location = function + | Prim (loc, _, _, _) + | Int (loc, _) + | String (loc, _) + | Bytes (loc, _) + | Seq (loc, _) -> + loc + +let kind_equal a b = + match (a, b) with + | (Int_kind, Int_kind) + | (String_kind, String_kind) + | (Bytes_kind, Bytes_kind) + | (Prim_kind, Prim_kind) + | (Seq_kind, Seq_kind) -> + true + | _ -> + false + +let kind = function + | Int _ -> + Int_kind + | String _ -> + String_kind + | Bytes _ -> + Bytes_kind + | Prim _ -> + Prim_kind + | Seq _ -> + Seq_kind + +let unexpected expr exp_kinds exp_ns exp_prims = + match expr with + | Int (loc, _) -> + Invalid_kind (loc, Prim_kind :: exp_kinds, Int_kind) + | String (loc, _) -> + Invalid_kind (loc, Prim_kind :: exp_kinds, String_kind) + | Bytes (loc, _) -> + Invalid_kind (loc, Prim_kind :: exp_kinds, Bytes_kind) + | Seq (loc, _) -> + Invalid_kind (loc, Prim_kind :: exp_kinds, Seq_kind) + | Prim (loc, name, _, _) -> ( + let open Michelson_v1_primitives in + match (namespace name, exp_ns) with + | (Type_namespace, Type_namespace) + | (Instr_namespace, Instr_namespace) + | (Constant_namespace, Constant_namespace) -> + Invalid_primitive (loc, exp_prims, name) + | (ns, _) -> + Invalid_namespace (loc, name, exp_ns, ns) ) + +let check_kind kinds expr = + let kind = kind expr in + if List.exists (kind_equal kind) kinds then ok_unit + else + let loc = location expr in + error (Invalid_kind (loc, kinds, kind)) + +(* ---- Lists, Sets and Maps ----------------------------------------------- *) + +let list_empty : 'a Script_typed_ir.boxed_list = + let open Script_typed_ir in + {elements = []; length = 0} + +let list_cons : + 'a -> 'a Script_typed_ir.boxed_list -> 'a Script_typed_ir.boxed_list = + fun elt l -> + let open Script_typed_ir in + {length = 1 + l.length; elements = elt :: l.elements} + +let wrap_compare compare a b = + let res = compare a b in + if Compare.Int.(res = 0) then 0 else if Compare.Int.(res > 0) then 1 else -1 + +let compare_address (x, ex) (y, ey) = + let lres = Contract.compare x y in + if Compare.Int.(lres = 0) then Compare.String.compare ex ey else lres + +let rec compare_comparable : type a. a comparable_ty -> a -> a -> int = + fun kind -> + match kind with + | Unit_key _ -> + fun () () -> 0 + | Never_key _ -> ( + function _ -> . ) + | Signature_key _ -> + wrap_compare Signature.compare + | String_key _ -> + wrap_compare Compare.String.compare + | Bool_key _ -> + wrap_compare Compare.Bool.compare + | Mutez_key _ -> + wrap_compare Tez.compare + | Key_hash_key _ -> + wrap_compare Signature.Public_key_hash.compare + | Key_key _ -> + wrap_compare Signature.Public_key.compare + | Int_key _ -> + wrap_compare Script_int.compare + | Nat_key _ -> + wrap_compare Script_int.compare + | Timestamp_key _ -> + wrap_compare Script_timestamp.compare + | Address_key _ -> + wrap_compare compare_address + | Bytes_key _ -> + wrap_compare Compare.Bytes.compare + | Chain_id_key _ -> + wrap_compare Chain_id.compare + | Pair_key ((tl, _), (tr, _), _) -> + fun (lx, rx) (ly, ry) -> + let lres = compare_comparable tl lx ly in + if Compare.Int.(lres = 0) then compare_comparable tr rx ry else lres + | Union_key ((tl, _), (tr, _), _) -> ( + fun x y -> + match (x, y) with + | (L x, L y) -> + compare_comparable tl x y + | (L _, R _) -> + -1 + | (R _, L _) -> + 1 + | (R x, R y) -> + compare_comparable tr x y ) + | Option_key (t, _) -> ( + fun x y -> + match (x, y) with + | (None, None) -> + 0 + | (None, Some _) -> + -1 + | (Some _, None) -> + 1 + | (Some x, Some y) -> + compare_comparable t x y ) + +let empty_set : type a. a comparable_ty -> a set = + fun ty -> + let module OPS = Set.Make (struct + type t = a + + let compare = compare_comparable ty + end) in + ( module struct + type elt = a + + let elt_ty = ty + + module OPS = OPS + + let boxed = OPS.empty + + let size = 0 + end ) + +let set_update : type a. a -> bool -> a set -> a set = + fun v b (module Box) -> + ( module struct + type elt = a + + let elt_ty = Box.elt_ty + + module OPS = Box.OPS + + let boxed = + if b then Box.OPS.add v Box.boxed else Box.OPS.remove v Box.boxed + + let size = + let mem = Box.OPS.mem v Box.boxed in + if mem then if b then Box.size else Box.size - 1 + else if b then Box.size + 1 + else Box.size + end ) + +let set_mem : type elt. elt -> elt set -> bool = + fun v (module Box) -> Box.OPS.mem v Box.boxed + +let set_fold : type elt acc. (elt -> acc -> acc) -> elt set -> acc -> acc = + fun f (module Box) -> Box.OPS.fold f Box.boxed + +let set_size : type elt. elt set -> Script_int.n Script_int.num = + fun (module Box) -> Script_int.(abs (of_int Box.size)) + +let map_key_ty : type a b. (a, b) map -> a comparable_ty = + fun (module Box) -> Box.key_ty + +let empty_map : type a b. a comparable_ty -> (a, b) map = + fun ty -> + let module OPS = Map.Make (struct + type t = a + + let compare = compare_comparable ty + end) in + ( module struct + type key = a + + type value = b + + let key_ty = ty + + module OPS = OPS + + let boxed = (OPS.empty, 0) + end ) + +let map_get : type key value. key -> (key, value) map -> value option = + fun k (module Box) -> Box.OPS.find_opt k (fst Box.boxed) + +let map_update : type a b. a -> b option -> (a, b) map -> (a, b) map = + fun k v (module Box) -> + ( module struct + type key = a + + type value = b + + let key_ty = Box.key_ty + + module OPS = Box.OPS + + let boxed = + let (map, size) = Box.boxed in + let contains = Box.OPS.mem k map in + match v with + | Some v -> + (Box.OPS.add k v map, size + if contains then 0 else 1) + | None -> + (Box.OPS.remove k map, size - if contains then 1 else 0) + end ) + +let map_mem : type key value. key -> (key, value) map -> bool = + fun k (module Box) -> Box.OPS.mem k (fst Box.boxed) + +let map_fold : + type key value acc. + (key -> value -> acc -> acc) -> (key, value) map -> acc -> acc = + fun f (module Box) -> Box.OPS.fold f (fst Box.boxed) + +let map_size : type key value. (key, value) map -> Script_int.n Script_int.num + = + fun (module Box) -> Script_int.(abs (of_int (snd Box.boxed))) + +(* ---- Unparsing (Typed IR -> Untyped expressions) of types -----------------*) + +(* This part contains the unparsing that does not depend on parsing + (everything that cannot contain a lambda). The rest is located at + the end of the file. *) + +let rec ty_of_comparable_ty : type a. a comparable_ty -> a ty = function + | Unit_key tname -> + Unit_t tname + | Never_key tname -> + Never_t tname + | Int_key tname -> + Int_t tname + | Nat_key tname -> + Nat_t tname + | Signature_key tname -> + Signature_t tname + | String_key tname -> + String_t tname + | Bytes_key tname -> + Bytes_t tname + | Mutez_key tname -> + Mutez_t tname + | Bool_key tname -> + Bool_t tname + | Key_hash_key tname -> + Key_hash_t tname + | Key_key tname -> + Key_t tname + | Timestamp_key tname -> + Timestamp_t tname + | Address_key tname -> + Address_t tname + | Chain_id_key tname -> + Chain_id_t tname + | Pair_key ((l, al), (r, ar), tname) -> + Pair_t + ( (ty_of_comparable_ty l, al, None), + (ty_of_comparable_ty r, ar, None), + tname ) + | Union_key ((l, al), (r, ar), tname) -> + Union_t ((ty_of_comparable_ty l, al), (ty_of_comparable_ty r, ar), tname) + | Option_key (t, tname) -> + Option_t (ty_of_comparable_ty t, tname) + +let add_field_annot a var = function + | Prim (loc, prim, args, annots) -> + Prim + ( loc, + prim, + args, + annots @ unparse_field_annot a @ unparse_var_annot var ) + | expr -> + expr + +let rec unparse_comparable_ty : type a. a comparable_ty -> Script.node = + function + | Unit_key tname -> + Prim (-1, T_unit, [], unparse_type_annot tname) + | Never_key tname -> + Prim (-1, T_never, [], unparse_type_annot tname) + | Int_key tname -> + Prim (-1, T_int, [], unparse_type_annot tname) + | Nat_key tname -> + Prim (-1, T_nat, [], unparse_type_annot tname) + | Signature_key tname -> + Prim (-1, T_signature, [], unparse_type_annot tname) + | String_key tname -> + Prim (-1, T_string, [], unparse_type_annot tname) + | Bytes_key tname -> + Prim (-1, T_bytes, [], unparse_type_annot tname) + | Mutez_key tname -> + Prim (-1, T_mutez, [], unparse_type_annot tname) + | Bool_key tname -> + Prim (-1, T_bool, [], unparse_type_annot tname) + | Key_hash_key tname -> + Prim (-1, T_key_hash, [], unparse_type_annot tname) + | Key_key tname -> + Prim (-1, T_key, [], unparse_type_annot tname) + | Timestamp_key tname -> + Prim (-1, T_timestamp, [], unparse_type_annot tname) + | Address_key tname -> + Prim (-1, T_address, [], unparse_type_annot tname) + | Chain_id_key tname -> + Prim (-1, T_chain_id, [], unparse_type_annot tname) + | Pair_key ((l, al), (r, ar), pname) -> ( + let tl = add_field_annot al None (unparse_comparable_ty l) in + let tr = add_field_annot ar None (unparse_comparable_ty r) in + (* Fold [pair a1 (pair ... (pair an-1 an))] into [pair a1 ... an] *) + (* Note that the folding does not happen if the pair on the right has a + field annotation because this annotation would be lost *) + match tr with + | Prim (_, T_pair, ts, []) -> + Prim (-1, T_pair, tl :: ts, unparse_type_annot pname) + | _ -> + Prim (-1, T_pair, [tl; tr], unparse_type_annot pname) ) + | Union_key ((l, al), (r, ar), tname) -> + let tl = add_field_annot al None (unparse_comparable_ty l) in + let tr = add_field_annot ar None (unparse_comparable_ty r) in + Prim (-1, T_or, [tl; tr], unparse_type_annot tname) + | Option_key (t, tname) -> + Prim (-1, T_option, [unparse_comparable_ty t], unparse_type_annot tname) + +let unparse_memo_size memo_size = + let z = Sapling.Memo_size.unparse_to_z memo_size in + Int (-1, z) + +let rec unparse_ty : + type a. context -> a ty -> (Script.node * context) tzresult = + fun ctxt ty -> + Gas.consume ctxt Unparse_costs.unparse_type_cycle + >>? fun ctxt -> + let return ctxt (name, args, annot) = + let result = Prim (-1, name, args, annot) in + ok (result, ctxt) + in + match ty with + | Unit_t tname -> + return ctxt (T_unit, [], unparse_type_annot tname) + | Int_t tname -> + return ctxt (T_int, [], unparse_type_annot tname) + | Nat_t tname -> + return ctxt (T_nat, [], unparse_type_annot tname) + | Signature_t tname -> + return ctxt (T_signature, [], unparse_type_annot tname) + | String_t tname -> + return ctxt (T_string, [], unparse_type_annot tname) + | Bytes_t tname -> + return ctxt (T_bytes, [], unparse_type_annot tname) + | Mutez_t tname -> + return ctxt (T_mutez, [], unparse_type_annot tname) + | Bool_t tname -> + return ctxt (T_bool, [], unparse_type_annot tname) + | Key_hash_t tname -> + return ctxt (T_key_hash, [], unparse_type_annot tname) + | Key_t tname -> + return ctxt (T_key, [], unparse_type_annot tname) + | Timestamp_t tname -> + return ctxt (T_timestamp, [], unparse_type_annot tname) + | Address_t tname -> + return ctxt (T_address, [], unparse_type_annot tname) + | Operation_t tname -> + return ctxt (T_operation, [], unparse_type_annot tname) + | Chain_id_t tname -> + return ctxt (T_chain_id, [], unparse_type_annot tname) + | Never_t tname -> + return ctxt (T_never, [], unparse_type_annot tname) + | Bls12_381_g1_t tname -> + return ctxt (T_bls12_381_g1, [], unparse_type_annot tname) + | Bls12_381_g2_t tname -> + return ctxt (T_bls12_381_g2, [], unparse_type_annot tname) + | Bls12_381_fr_t tname -> + return ctxt (T_bls12_381_fr, [], unparse_type_annot tname) + | Contract_t (ut, tname) -> + unparse_ty ctxt ut + >>? fun (t, ctxt) -> + return ctxt (T_contract, [t], unparse_type_annot tname) + | Pair_t ((utl, l_field, l_var), (utr, r_field, r_var), tname) -> + let annot = unparse_type_annot tname in + unparse_ty ctxt utl + >>? fun (utl, ctxt) -> + let tl = add_field_annot l_field l_var utl in + unparse_ty ctxt utr + >>? fun (utr, ctxt) -> + let tr = add_field_annot r_field r_var utr in + (* Fold [pair a1 (pair ... (pair an-1 an))] into [pair a1 ... an] *) + (* Note that the folding does not happen if the pair on the right has an + annotation because this annotation would be lost *) + return + ctxt + ( match tr with + | Prim (_, T_pair, ts, []) -> + (T_pair, tl :: ts, annot) + | _ -> + (T_pair, [tl; tr], annot) ) + | Union_t ((utl, l_field), (utr, r_field), tname) -> + let annot = unparse_type_annot tname in + unparse_ty ctxt utl + >>? fun (utl, ctxt) -> + let tl = add_field_annot l_field None utl in + unparse_ty ctxt utr + >>? fun (utr, ctxt) -> + let tr = add_field_annot r_field None utr in + return ctxt (T_or, [tl; tr], annot) + | Lambda_t (uta, utr, tname) -> + unparse_ty ctxt uta + >>? fun (ta, ctxt) -> + unparse_ty ctxt utr + >>? fun (tr, ctxt) -> + return ctxt (T_lambda, [ta; tr], unparse_type_annot tname) + | Option_t (ut, tname) -> + let annot = unparse_type_annot tname in + unparse_ty ctxt ut + >>? fun (ut, ctxt) -> return ctxt (T_option, [ut], annot) + | List_t (ut, tname) -> + unparse_ty ctxt ut + >>? fun (t, ctxt) -> return ctxt (T_list, [t], unparse_type_annot tname) + | Ticket_t (ut, tname) -> + let t = unparse_comparable_ty ut in + return ctxt (T_ticket, [t], unparse_type_annot tname) + | Set_t (ut, tname) -> + let t = unparse_comparable_ty ut in + return ctxt (T_set, [t], unparse_type_annot tname) + | Map_t (uta, utr, tname) -> + let ta = unparse_comparable_ty uta in + unparse_ty ctxt utr + >>? fun (tr, ctxt) -> + return ctxt (T_map, [ta; tr], unparse_type_annot tname) + | Big_map_t (uta, utr, tname) -> + let ta = unparse_comparable_ty uta in + unparse_ty ctxt utr + >>? fun (tr, ctxt) -> + return ctxt (T_big_map, [ta; tr], unparse_type_annot tname) + | Sapling_transaction_t (memo_size, tname) -> + return + ctxt + ( T_sapling_transaction, + [unparse_memo_size memo_size], + unparse_type_annot tname ) + | Sapling_state_t (memo_size, tname) -> + return + ctxt + ( T_sapling_state, + [unparse_memo_size memo_size], + unparse_type_annot tname ) + +let rec strip_var_annots = function + | (Int _ | String _ | Bytes _) as atom -> + atom + | Seq (loc, args) -> + Seq (loc, List.map strip_var_annots args) + | Prim (loc, name, args, annots) -> + let not_var_annot s = Compare.Char.(s.[0] <> '@') in + let annots = List.filter not_var_annot annots in + Prim (loc, name, List.map strip_var_annots args, annots) + +let serialize_ty_for_error ctxt ty = + unparse_ty ctxt ty + >>? (fun (ty, ctxt) -> + Gas.consume ctxt (Script.strip_locations_cost ty) + >|? fun ctxt -> (Micheline.strip_locations (strip_var_annots ty), ctxt)) + |> record_trace Cannot_serialize_error + +let rec comparable_ty_of_ty : + type a. + context -> Script.location -> a ty -> (a comparable_ty * context) tzresult + = + fun ctxt loc ty -> + Gas.consume ctxt Typecheck_costs.comparable_ty_of_ty_cycle + >>? fun ctxt -> + match ty with + | Unit_t tname -> + ok ((Unit_key tname : a comparable_ty), ctxt) + | Never_t tname -> + ok (Never_key tname, ctxt) + | Int_t tname -> + ok (Int_key tname, ctxt) + | Nat_t tname -> + ok (Nat_key tname, ctxt) + | Signature_t tname -> + ok (Signature_key tname, ctxt) + | String_t tname -> + ok (String_key tname, ctxt) + | Bytes_t tname -> + ok (Bytes_key tname, ctxt) + | Mutez_t tname -> + ok (Mutez_key tname, ctxt) + | Bool_t tname -> + ok (Bool_key tname, ctxt) + | Key_hash_t tname -> + ok (Key_hash_key tname, ctxt) + | Key_t tname -> + ok (Key_key tname, ctxt) + | Timestamp_t tname -> + ok (Timestamp_key tname, ctxt) + | Address_t tname -> + ok (Address_key tname, ctxt) + | Chain_id_t tname -> + ok (Chain_id_key tname, ctxt) + | Pair_t ((l, al, _), (r, ar, _), pname) -> + comparable_ty_of_ty ctxt loc l + >>? fun (lty, ctxt) -> + comparable_ty_of_ty ctxt loc r + >|? fun (rty, ctxt) -> (Pair_key ((lty, al), (rty, ar), pname), ctxt) + | Union_t ((l, al), (r, ar), tname) -> + comparable_ty_of_ty ctxt loc l + >>? fun (lty, ctxt) -> + comparable_ty_of_ty ctxt loc r + >|? fun (rty, ctxt) -> (Union_key ((lty, al), (rty, ar), tname), ctxt) + | Option_t (tt, tname) -> + comparable_ty_of_ty ctxt loc tt + >|? fun (ty, ctxt) -> (Option_key (ty, tname), ctxt) + | Lambda_t _ + | List_t _ + | Ticket_t _ + | Set_t _ + | Map_t _ + | Big_map_t _ + | Contract_t _ + | Operation_t _ + | Bls12_381_fr_t _ + | Bls12_381_g1_t _ + | Bls12_381_g2_t _ + | Sapling_state_t _ + | Sapling_transaction_t _ -> + serialize_ty_for_error ctxt ty + >>? fun (t, _ctxt) -> error (Comparable_type_expected (loc, t)) + +let rec unparse_stack : + type a. + context -> + a stack_ty -> + ((Script.expr * Script.annot) list * context) tzresult = + fun ctxt -> function + | Empty_t -> + ok ([], ctxt) + | Item_t (ty, rest, annot) -> + unparse_ty ctxt ty + >>? fun (uty, ctxt) -> + unparse_stack ctxt rest + >|? fun (urest, ctxt) -> + ((strip_locations uty, unparse_var_annot annot) :: urest, ctxt) + +let serialize_stack_for_error ctxt stack_ty = + record_trace Cannot_serialize_error (unparse_stack ctxt stack_ty) + +let name_of_ty : type a. a ty -> type_annot option = function + | Unit_t tname -> + tname + | Int_t tname -> + tname + | Nat_t tname -> + tname + | String_t tname -> + tname + | Bytes_t tname -> + tname + | Mutez_t tname -> + tname + | Bool_t tname -> + tname + | Key_hash_t tname -> + tname + | Key_t tname -> + tname + | Timestamp_t tname -> + tname + | Address_t tname -> + tname + | Signature_t tname -> + tname + | Operation_t tname -> + tname + | Chain_id_t tname -> + tname + | Never_t tname -> + tname + | Contract_t (_, tname) -> + tname + | Pair_t (_, _, tname) -> + tname + | Union_t (_, _, tname) -> + tname + | Lambda_t (_, _, tname) -> + tname + | Option_t (_, tname) -> + tname + | List_t (_, tname) -> + tname + | Ticket_t (_, tname) -> + tname + | Set_t (_, tname) -> + tname + | Map_t (_, _, tname) -> + tname + | Big_map_t (_, _, tname) -> + tname + | Bls12_381_g1_t tname -> + tname + | Bls12_381_g2_t tname -> + tname + | Bls12_381_fr_t tname -> + tname + | Sapling_state_t (_, tname) -> + tname + | Sapling_transaction_t (_, tname) -> + tname + +let unparse_unit ctxt () = ok (Prim (-1, D_Unit, [], []), ctxt) + +let unparse_int ctxt v = ok (Int (-1, Script_int.to_zint v), ctxt) + +let unparse_nat ctxt v = ok (Int (-1, Script_int.to_zint v), ctxt) + +let unparse_string ctxt s = ok (String (-1, s), ctxt) + +let unparse_bytes ctxt s = ok (Bytes (-1, s), ctxt) + +let unparse_bool ctxt b = + ok (Prim (-1, (if b then D_True else D_False), [], []), ctxt) + +let unparse_timestamp ctxt mode t = + match mode with + | Optimized | Optimized_legacy -> + ok (Int (-1, Script_timestamp.to_zint t), ctxt) + | Readable -> ( + Gas.consume ctxt Unparse_costs.timestamp_readable + >>? fun ctxt -> + match Script_timestamp.to_notation t with + | None -> + ok (Int (-1, Script_timestamp.to_zint t), ctxt) + | Some s -> + ok (String (-1, s), ctxt) ) + +let unparse_address ctxt mode (c, entrypoint) = + Gas.consume ctxt Unparse_costs.contract + >>? fun ctxt -> + ( match entrypoint with + (* given parse_address, this should not happen *) + | "" -> + error Unparsing_invariant_violated + | _ -> + ok () ) + >|? fun () -> + match mode with + | Optimized | Optimized_legacy -> + let entrypoint = + match entrypoint with "default" -> "" | name -> name + in + let bytes = + Data_encoding.Binary.to_bytes_exn + Data_encoding.(tup2 Contract.encoding Variable.string) + (c, entrypoint) + in + (Bytes (-1, bytes), ctxt) + | Readable -> + let notation = + match entrypoint with + | "default" -> + Contract.to_b58check c + | entrypoint -> + Contract.to_b58check c ^ "%" ^ entrypoint + in + (String (-1, notation), ctxt) + +let unparse_contract ctxt mode (_, address) = unparse_address ctxt mode address + +let unparse_signature ctxt mode s = + match mode with + | Optimized | Optimized_legacy -> + Gas.consume ctxt Unparse_costs.signature_optimized + >|? fun ctxt -> + let bytes = Data_encoding.Binary.to_bytes_exn Signature.encoding s in + (Bytes (-1, bytes), ctxt) + | Readable -> + Gas.consume ctxt Unparse_costs.signature_readable + >|? fun ctxt -> (String (-1, Signature.to_b58check s), ctxt) + +let unparse_mutez ctxt v = ok (Int (-1, Z.of_int64 (Tez.to_mutez v)), ctxt) + +let unparse_key ctxt mode k = + match mode with + | Optimized | Optimized_legacy -> + Gas.consume ctxt Unparse_costs.public_key_optimized + >|? fun ctxt -> + let bytes = + Data_encoding.Binary.to_bytes_exn Signature.Public_key.encoding k + in + (Bytes (-1, bytes), ctxt) + | Readable -> + Gas.consume ctxt Unparse_costs.public_key_readable + >|? fun ctxt -> (String (-1, Signature.Public_key.to_b58check k), ctxt) + +let unparse_key_hash ctxt mode k = + match mode with + | Optimized | Optimized_legacy -> + Gas.consume ctxt Unparse_costs.key_hash_optimized + >|? fun ctxt -> + let bytes = + Data_encoding.Binary.to_bytes_exn Signature.Public_key_hash.encoding k + in + (Bytes (-1, bytes), ctxt) + | Readable -> + Gas.consume ctxt Unparse_costs.key_hash_readable + >|? fun ctxt -> + (String (-1, Signature.Public_key_hash.to_b58check k), ctxt) + +let unparse_operation ctxt (op, _big_map_diff) = + let bytes = + Data_encoding.Binary.to_bytes_exn Operation.internal_operation_encoding op + in + Gas.consume ctxt (Unparse_costs.operation bytes) + >|? fun ctxt -> (Bytes (-1, bytes), ctxt) + +let unparse_chain_id ctxt mode chain_id = + match mode with + | Optimized | Optimized_legacy -> + Gas.consume ctxt Unparse_costs.chain_id_optimized + >|? fun ctxt -> + let bytes = + Data_encoding.Binary.to_bytes_exn Chain_id.encoding chain_id + in + (Bytes (-1, bytes), ctxt) + | Readable -> + Gas.consume ctxt Unparse_costs.chain_id_readable + >|? fun ctxt -> (String (-1, Chain_id.to_b58check chain_id), ctxt) + +let unparse_bls12_381_g1 ctxt x = + Gas.consume ctxt Unparse_costs.bls12_381_g1 + >|? fun ctxt -> + let bytes = Bls12_381.G1.to_bytes x in + (Bytes (-1, bytes), ctxt) + +let unparse_bls12_381_g2 ctxt x = + Gas.consume ctxt Unparse_costs.bls12_381_g2 + >|? fun ctxt -> + let bytes = Bls12_381.G2.to_bytes x in + (Bytes (-1, bytes), ctxt) + +let unparse_bls12_381_fr ctxt x = + Gas.consume ctxt Unparse_costs.bls12_381_fr + >|? fun ctxt -> + let bytes = Bls12_381.Fr.to_bytes x in + (Bytes (-1, bytes), ctxt) + +(* -- Unparsing data of complex types -- *) + +type ('ty, 'depth) comb_witness = + | Comb_Pair : ('t, 'd) comb_witness -> (_ * 't, unit -> 'd) comb_witness + | Comb_Any : (_, _) comb_witness + +let unparse_pair (type r) unparse_l unparse_r ctxt mode + (r_comb_witness : (r, unit -> unit -> _) comb_witness) (l, (r : r)) = + unparse_l ctxt l + >>=? fun (l, ctxt) -> + unparse_r ctxt r + >|=? fun (r, ctxt) -> + (* Fold combs. + For combs, three notations are supported: + - a) [Pair x1 (Pair x2 ... (Pair xn-1 xn) ...)], + - b) [Pair x1 x2 ... xn-1 xn], and + - c) [{x1; x2; ...; xn-1; xn}]. + In readable mode, we always use b), + in optimized mode we use the shortest to serialize: + - for n=2, [Pair x1 x2], + - for n=3, [Pair x1 (Pair x2 x3)], + - for n>=4, [{x1; x2; ...; xn}]. + *) + let res = + match (mode, r_comb_witness, r) with + | (Optimized, Comb_Pair _, Micheline.Seq (_, r)) -> + (* Optimized case n > 4 *) + Micheline.Seq (-1, l :: r) + | ( Optimized, + Comb_Pair (Comb_Pair _), + Prim (_, D_Pair, [x2; Prim (_, D_Pair, [x3; x4], [])], []) ) -> + (* Optimized case n = 4 *) + Micheline.Seq (-1, [l; x2; x3; x4]) + | (Readable, Comb_Pair _, Prim (_, D_Pair, xs, [])) -> + (* Readable case n > 2 *) + Prim (-1, D_Pair, l :: xs, []) + | _ -> + (* The remaining cases are: + - Optimized n = 2, + - Optimized n = 3, and + - Readable n = 2, + - Optimized_legacy, any n *) + Prim (-1, D_Pair, [l; r], []) + in + (res, ctxt) + +let unparse_union unparse_l unparse_r ctxt = function + | L l -> + unparse_l ctxt l >|=? fun (l, ctxt) -> (Prim (-1, D_Left, [l], []), ctxt) + | R r -> + unparse_r ctxt r >|=? fun (r, ctxt) -> (Prim (-1, D_Right, [r], []), ctxt) + +let unparse_option unparse_v ctxt = function + | Some v -> + unparse_v ctxt v >|=? fun (v, ctxt) -> (Prim (-1, D_Some, [v], []), ctxt) + | None -> + return (Prim (-1, D_None, [], []), ctxt) + +(* -- Unparsing data of comparable types -- *) + +let comparable_comb_witness2 : + type t. t comparable_ty -> (t, unit -> unit -> unit) comb_witness = + function + | Pair_key (_, (Pair_key _, _), _) -> + Comb_Pair (Comb_Pair Comb_Any) + | Pair_key _ -> + Comb_Pair Comb_Any + | _ -> + Comb_Any + +let rec unparse_comparable_data : + type a. + context -> + unparsing_mode -> + a comparable_ty -> + a -> + (Script.node * context) tzresult Lwt.t = + fun ctxt mode ty a -> + (* No need for stack_depth here. Unlike [unparse_data], + [unparse_comparable_data] doesn't call [unparse_code]. + The stack depth is bounded by the type depth, currently bounded + by 1000 (michelson_maximum_type_size). *) + Gas.consume ctxt Unparse_costs.unparse_data_cycle + (* We could have a smaller cost but let's keep it consistent with + [unparse_data] for now. *) + >>?= fun ctxt -> + match (ty, a) with + | (Unit_key _, v) -> + Lwt.return @@ unparse_unit ctxt v + | (Int_key _, v) -> + Lwt.return @@ unparse_int ctxt v + | (Nat_key _, v) -> + Lwt.return @@ unparse_nat ctxt v + | (String_key _, s) -> + Lwt.return @@ unparse_string ctxt s + | (Bytes_key _, s) -> + Lwt.return @@ unparse_bytes ctxt s + | (Bool_key _, b) -> + Lwt.return @@ unparse_bool ctxt b + | (Timestamp_key _, t) -> + Lwt.return @@ unparse_timestamp ctxt mode t + | (Address_key _, address) -> + Lwt.return @@ unparse_address ctxt mode address + | (Signature_key _, s) -> + Lwt.return @@ unparse_signature ctxt mode s + | (Mutez_key _, v) -> + Lwt.return @@ unparse_mutez ctxt v + | (Key_key _, k) -> + Lwt.return @@ unparse_key ctxt mode k + | (Key_hash_key _, k) -> + Lwt.return @@ unparse_key_hash ctxt mode k + | (Chain_id_key _, chain_id) -> + Lwt.return @@ unparse_chain_id ctxt mode chain_id + | (Pair_key ((tl, _), (tr, _), _), pair) -> + let r_witness = comparable_comb_witness2 tr in + let unparse_l ctxt v = unparse_comparable_data ctxt mode tl v in + let unparse_r ctxt v = unparse_comparable_data ctxt mode tr v in + unparse_pair unparse_l unparse_r ctxt mode r_witness pair + | (Union_key ((tl, _), (tr, _), _), v) -> + let unparse_l ctxt v = unparse_comparable_data ctxt mode tl v in + let unparse_r ctxt v = unparse_comparable_data ctxt mode tr v in + unparse_union unparse_l unparse_r ctxt v + | (Option_key (t, _), v) -> + let unparse_v ctxt v = unparse_comparable_data ctxt mode t v in + unparse_option unparse_v ctxt v + | (Never_key _, _) -> + . + +let pack_node unparsed ctxt = + Gas.consume ctxt (Script.strip_locations_cost unparsed) + >>? fun ctxt -> + let bytes = + Data_encoding.Binary.to_bytes_exn + expr_encoding + (Micheline.strip_locations unparsed) + in + Gas.consume ctxt (Script.serialized_cost bytes) + >>? fun ctxt -> + let bytes = Bytes.cat (Bytes.of_string "\005") bytes in + Gas.consume ctxt (Script.serialized_cost bytes) >|? fun ctxt -> (bytes, ctxt) + +let pack_comparable_data ctxt typ data ~mode = + unparse_comparable_data ctxt mode typ data + >>=? fun (unparsed, ctxt) -> Lwt.return @@ pack_node unparsed ctxt + +let hash_bytes ctxt bytes = + Gas.consume ctxt (Michelson_v1_gas.Cost_of.Interpreter.blake2b bytes) + >|? fun ctxt -> (Script_expr_hash.(hash_bytes [bytes]), ctxt) + +let hash_comparable_data ctxt typ data = + pack_comparable_data ctxt typ data ~mode:Optimized_legacy + >>=? fun (bytes, ctxt) -> Lwt.return @@ hash_bytes ctxt bytes + +(* ---- Tickets ------------------------------------------------------------ *) + +(* + All comparable types are dupable, this function exists only to not forget + checking this property when adding new types. +*) +let check_dupable_comparable_ty : type a. a comparable_ty -> unit = function + | Unit_key _ + | Never_key _ + | Int_key _ + | Nat_key _ + | Signature_key _ + | String_key _ + | Bytes_key _ + | Mutez_key _ + | Bool_key _ + | Key_hash_key _ + | Key_key _ + | Timestamp_key _ + | Chain_id_key _ + | Address_key _ + | Pair_key _ + | Union_key _ + | Option_key _ -> + () + +let rec check_dupable_ty : + type a. context -> location -> a ty -> context tzresult = + fun ctxt loc ty -> + Gas.consume ctxt Typecheck_costs.check_dupable_cycle + >>? fun ctxt -> + match ty with + | Unit_t _ -> + ok ctxt + | Int_t _ -> + ok ctxt + | Nat_t _ -> + ok ctxt + | Signature_t _ -> + ok ctxt + | String_t _ -> + ok ctxt + | Bytes_t _ -> + ok ctxt + | Mutez_t _ -> + ok ctxt + | Key_hash_t _ -> + ok ctxt + | Key_t _ -> + ok ctxt + | Timestamp_t _ -> + ok ctxt + | Address_t _ -> + ok ctxt + | Bool_t _ -> + ok ctxt + | Contract_t (_, _) -> + ok ctxt + | Operation_t _ -> + ok ctxt + | Chain_id_t _ -> + ok ctxt + | Never_t _ -> + ok ctxt + | Bls12_381_g1_t _ -> + ok ctxt + | Bls12_381_g2_t _ -> + ok ctxt + | Bls12_381_fr_t _ -> + ok ctxt + | Sapling_state_t _ -> + ok ctxt + | Sapling_transaction_t _ -> + ok ctxt + | Ticket_t _ -> + error (Unexpected_ticket loc) + | Pair_t ((ty_a, _, _), (ty_b, _, _), _) -> + check_dupable_ty ctxt loc ty_a + >>? fun ctxt -> check_dupable_ty ctxt loc ty_b + | Union_t ((ty_a, _), (ty_b, _), _) -> + check_dupable_ty ctxt loc ty_a + >>? fun ctxt -> check_dupable_ty ctxt loc ty_b + | Lambda_t (_, _, _) -> + (* + Lambda are dupable as long as: + - they don't contain non-dupable values, e.g. in `PUSH` + (mosty non-dupable values should probably be considered forged) + - they are not the result of a partial application on a non-dupable + value. `APPLY` rejects non-packable types (because of `PUSH`). + Hence non-dupable should imply non-packable. + *) + ok ctxt + | Option_t (ty, _) -> + check_dupable_ty ctxt loc ty + | List_t (ty, _) -> + check_dupable_ty ctxt loc ty + | Set_t (key_ty, _) -> + let () = check_dupable_comparable_ty key_ty in + ok ctxt + | Map_t (key_ty, val_ty, _) -> + let () = check_dupable_comparable_ty key_ty in + check_dupable_ty ctxt loc val_ty + | Big_map_t (key_ty, val_ty, _) -> + let () = check_dupable_comparable_ty key_ty in + check_dupable_ty ctxt loc val_ty + +(* ---- Equality witnesses --------------------------------------------------*) + +type ('ta, 'tb) eq = Eq : ('same, 'same) eq + +let record_inconsistent ctxt ta tb = + record_trace_eval (fun () -> + serialize_ty_for_error ctxt ta + >>? fun (ta, ctxt) -> + serialize_ty_for_error ctxt tb + >|? fun (tb, _ctxt) -> Inconsistent_types (ta, tb)) + +let record_inconsistent_type_annotations ctxt loc ta tb = + record_trace_eval (fun () -> + serialize_ty_for_error ctxt ta + >>? fun (ta, ctxt) -> + serialize_ty_for_error ctxt tb + >|? fun (tb, _ctxt) -> Inconsistent_type_annotations (loc, ta, tb)) + +let rec merge_comparable_types : + type ta tb. + legacy:bool -> + context -> + ta comparable_ty -> + tb comparable_ty -> + ((ta comparable_ty, tb comparable_ty) eq * ta comparable_ty * context) + tzresult = + fun ~legacy ctxt ta tb -> + Gas.consume ctxt Typecheck_costs.merge_cycle + >>? fun ctxt -> + match (ta, tb) with + | (Unit_key annot_a, Unit_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> + ( (Eq : (ta comparable_ty, tb comparable_ty) eq), + (Unit_key annot : ta comparable_ty), + ctxt ) + | (Never_key annot_a, Never_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Never_key annot, ctxt) + | (Int_key annot_a, Int_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Int_key annot, ctxt) + | (Nat_key annot_a, Nat_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Nat_key annot, ctxt) + | (Signature_key annot_a, Signature_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Signature_key annot, ctxt) + | (String_key annot_a, String_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, String_key annot, ctxt) + | (Bytes_key annot_a, Bytes_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Bytes_key annot, ctxt) + | (Mutez_key annot_a, Mutez_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Mutez_key annot, ctxt) + | (Bool_key annot_a, Bool_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Bool_key annot, ctxt) + | (Key_hash_key annot_a, Key_hash_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Key_hash_key annot, ctxt) + | (Key_key annot_a, Key_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Key_key annot, ctxt) + | (Timestamp_key annot_a, Timestamp_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Timestamp_key annot, ctxt) + | (Chain_id_key annot_a, Chain_id_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Chain_id_key annot, ctxt) + | (Address_key annot_a, Address_key annot_b) -> + merge_type_annot ~legacy annot_a annot_b + >|? fun annot -> (Eq, Address_key annot, ctxt) + | ( Pair_key ((left_a, annot_left_a), (right_a, annot_right_a), annot_a), + Pair_key ((left_b, annot_left_b), (right_b, annot_right_b), annot_b) ) -> + merge_type_annot ~legacy annot_a annot_b + >>? fun annot -> + merge_field_annot ~legacy annot_left_a annot_left_b + >>? fun annot_left -> + merge_field_annot ~legacy annot_right_a annot_right_b + >>? fun annot_right -> + merge_comparable_types ~legacy ctxt left_a left_b + >>? fun (Eq, left, ctxt) -> + merge_comparable_types ~legacy ctxt right_a right_b + >|? fun (Eq, right, ctxt) -> + ( (Eq : (ta comparable_ty, tb comparable_ty) eq), + Pair_key ((left, annot_left), (right, annot_right), annot), + ctxt ) + | ( Union_key ((left_a, annot_left_a), (right_a, annot_right_a), annot_a), + Union_key ((left_b, annot_left_b), (right_b, annot_right_b), annot_b) ) + -> + merge_type_annot ~legacy annot_a annot_b + >>? fun annot -> + merge_field_annot ~legacy annot_left_a annot_left_b + >>? fun annot_left -> + merge_field_annot ~legacy annot_right_a annot_right_b + >>? fun annot_right -> + merge_comparable_types ~legacy ctxt left_a left_b + >>? fun (Eq, left, ctxt) -> + merge_comparable_types ~legacy ctxt right_a right_b + >|? fun (Eq, right, ctxt) -> + ( (Eq : (ta comparable_ty, tb comparable_ty) eq), + Union_key ((left, annot_left), (right, annot_right), annot), + ctxt ) + | (Option_key (ta, annot_a), Option_key (tb, annot_b)) -> + merge_type_annot ~legacy annot_a annot_b + >>? fun annot -> + merge_comparable_types ~legacy ctxt ta tb + >|? fun (Eq, t, ctxt) -> + ( (Eq : (ta comparable_ty, tb comparable_ty) eq), + Option_key (t, annot), + ctxt ) + | (_, _) -> + serialize_ty_for_error ctxt (ty_of_comparable_ty ta) + >>? fun (ta, ctxt) -> + serialize_ty_for_error ctxt (ty_of_comparable_ty tb) + >>? fun (tb, _ctxt) -> error (Inconsistent_types (ta, tb)) + +let comparable_ty_eq : + type ta tb. + context -> + ta comparable_ty -> + tb comparable_ty -> + ((ta comparable_ty, tb comparable_ty) eq * context) tzresult = + fun ctxt ta tb -> + merge_comparable_types ~legacy:true ctxt ta tb + >|? fun (eq, _ty, ctxt) -> (eq, ctxt) + +let merge_memo_sizes ms1 ms2 = + if Sapling.Memo_size.equal ms1 ms2 then ok ms1 + else error (Inconsistent_memo_sizes (ms1, ms2)) + +let merge_types : + type a b. + legacy:bool -> + context -> + Script.location -> + a ty -> + b ty -> + ((a ty, b ty) eq * a ty * context) tzresult = + fun ~legacy ctxt loc ty1 ty2 -> + let merge_type_annot tn1 tn2 = + merge_type_annot ~legacy tn1 tn2 + |> record_inconsistent_type_annotations ctxt loc ty1 ty2 + in + let rec help : + type ta tb. + context -> + ta ty -> + tb ty -> + ((ta ty, tb ty) eq * ta ty * context) tzresult = + fun ctxt ty1 ty2 -> help0 ctxt ty1 ty2 |> record_inconsistent ctxt ty1 ty2 + and help0 : + type ta tb. + context -> + ta ty -> + tb ty -> + ((ta ty, tb ty) eq * ta ty * context) tzresult = + fun ctxt ty1 ty2 -> + Gas.consume ctxt Typecheck_costs.merge_cycle + >>? fun ctxt -> + match (ty1, ty2) with + | (Unit_t tn1, Unit_t tn2) -> + merge_type_annot tn1 tn2 + >|? fun tname -> + ((Eq : (ta ty, tb ty) eq), (Unit_t tname : ta ty), ctxt) + | (Int_t tn1, Int_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Int_t tname, ctxt) + | (Nat_t tn1, Nat_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Nat_t tname, ctxt) + | (Key_t tn1, Key_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Key_t tname, ctxt) + | (Key_hash_t tn1, Key_hash_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Key_hash_t tname, ctxt) + | (String_t tn1, String_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, String_t tname, ctxt) + | (Bytes_t tn1, Bytes_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Bytes_t tname, ctxt) + | (Signature_t tn1, Signature_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Signature_t tname, ctxt) + | (Mutez_t tn1, Mutez_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Mutez_t tname, ctxt) + | (Timestamp_t tn1, Timestamp_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Timestamp_t tname, ctxt) + | (Address_t tn1, Address_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Address_t tname, ctxt) + | (Bool_t tn1, Bool_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Bool_t tname, ctxt) + | (Chain_id_t tn1, Chain_id_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Chain_id_t tname, ctxt) + | (Never_t tn1, Never_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Never_t tname, ctxt) + | (Operation_t tn1, Operation_t tn2) -> + merge_type_annot tn1 tn2 >|? fun tname -> (Eq, Operation_t tname, ctxt) + | (Bls12_381_g1_t tn1, Bls12_381_g1_t tn2) -> + merge_type_annot tn1 tn2 + >|? fun tname -> (Eq, Bls12_381_g1_t tname, ctxt) + | (Bls12_381_g2_t tn1, Bls12_381_g2_t tn2) -> + merge_type_annot tn1 tn2 + >|? fun tname -> (Eq, Bls12_381_g2_t tname, ctxt) + | (Bls12_381_fr_t tn1, Bls12_381_fr_t tn2) -> + merge_type_annot tn1 tn2 + >|? fun tname -> (Eq, Bls12_381_fr_t tname, ctxt) + | (Map_t (tal, tar, tn1), Map_t (tbl, tbr, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + help ctxt tar tbr + >>? fun (Eq, value, ctxt) -> + merge_comparable_types ~legacy ctxt tal tbl + >|? fun (Eq, tk, ctxt) -> + ((Eq : (ta ty, tb ty) eq), Map_t (tk, value, tname), ctxt) + | (Big_map_t (tal, tar, tn1), Big_map_t (tbl, tbr, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + help ctxt tar tbr + >>? fun (Eq, value, ctxt) -> + merge_comparable_types ~legacy ctxt tal tbl + >|? fun (Eq, tk, ctxt) -> + ((Eq : (ta ty, tb ty) eq), Big_map_t (tk, value, tname), ctxt) + | (Set_t (ea, tn1), Set_t (eb, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + merge_comparable_types ~legacy ctxt ea eb + >|? fun (Eq, e, ctxt) -> + ((Eq : (ta ty, tb ty) eq), Set_t (e, tname), ctxt) + | (Ticket_t (ea, tn1), Ticket_t (eb, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + merge_comparable_types ~legacy ctxt ea eb + >|? fun (Eq, e, ctxt) -> + ((Eq : (ta ty, tb ty) eq), Ticket_t (e, tname), ctxt) + | ( Pair_t ((tal, l_field1, l_var1), (tar, r_field1, r_var1), tn1), + Pair_t ((tbl, l_field2, l_var2), (tbr, r_field2, r_var2), tn2) ) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + merge_field_annot ~legacy l_field1 l_field2 + >>? fun l_field -> + merge_field_annot ~legacy r_field1 r_field2 + >>? fun r_field -> + let l_var = merge_var_annot l_var1 l_var2 in + let r_var = merge_var_annot r_var1 r_var2 in + help ctxt tal tbl + >>? fun (Eq, left_ty, ctxt) -> + help ctxt tar tbr + >|? fun (Eq, right_ty, ctxt) -> + ( (Eq : (ta ty, tb ty) eq), + Pair_t ((left_ty, l_field, l_var), (right_ty, r_field, r_var), tname), + ctxt ) + | ( Union_t ((tal, tal_annot), (tar, tar_annot), tn1), + Union_t ((tbl, tbl_annot), (tbr, tbr_annot), tn2) ) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + merge_field_annot ~legacy tal_annot tbl_annot + >>? fun left_annot -> + merge_field_annot ~legacy tar_annot tbr_annot + >>? fun right_annot -> + help ctxt tal tbl + >>? fun (Eq, left_ty, ctxt) -> + help ctxt tar tbr + >|? fun (Eq, right_ty, ctxt) -> + ( (Eq : (ta ty, tb ty) eq), + Union_t ((left_ty, left_annot), (right_ty, right_annot), tname), + ctxt ) + | (Lambda_t (tal, tar, tn1), Lambda_t (tbl, tbr, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + help ctxt tal tbl + >>? fun (Eq, left_ty, ctxt) -> + help ctxt tar tbr + >|? fun (Eq, right_ty, ctxt) -> + ((Eq : (ta ty, tb ty) eq), Lambda_t (left_ty, right_ty, tname), ctxt) + | (Contract_t (tal, tn1), Contract_t (tbl, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + help ctxt tal tbl + >|? fun (Eq, arg_ty, ctxt) -> + ((Eq : (ta ty, tb ty) eq), Contract_t (arg_ty, tname), ctxt) + | (Option_t (tva, tn1), Option_t (tvb, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + help ctxt tva tvb + >|? fun (Eq, ty, ctxt) -> + ((Eq : (ta ty, tb ty) eq), Option_t (ty, tname), ctxt) + | (List_t (tva, tn1), List_t (tvb, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + help ctxt tva tvb + >|? fun (Eq, ty, ctxt) -> + ((Eq : (ta ty, tb ty) eq), List_t (ty, tname), ctxt) + | (Sapling_state_t (ms1, tn1), Sapling_state_t (ms2, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + merge_memo_sizes ms1 ms2 + >|? fun ms -> (Eq, Sapling_state_t (ms, tname), ctxt) + | (Sapling_transaction_t (ms1, tn1), Sapling_transaction_t (ms2, tn2)) -> + merge_type_annot tn1 tn2 + >>? fun tname -> + merge_memo_sizes ms1 ms2 + >|? fun ms -> (Eq, Sapling_transaction_t (ms, tname), ctxt) + | (_, _) -> + serialize_ty_for_error ctxt ty1 + >>? fun (ty1, ctxt) -> + serialize_ty_for_error ctxt ty2 + >>? fun (ty2, _ctxt) -> error (Inconsistent_types (ty1, ty2)) + in + help ctxt ty1 ty2 + [@@coq_axiom "non-top-level mutual recursion"] + +let ty_eq : + type ta tb. + context -> + Script.location -> + ta ty -> + tb ty -> + ((ta ty, tb ty) eq * context) tzresult = + fun ctxt loc ta tb -> + merge_types ~legacy:true ctxt loc ta tb >|? fun (eq, _ty, ctxt) -> (eq, ctxt) + +let merge_stacks : + type ta tb. + legacy:bool -> + Script.location -> + context -> + int -> + ta stack_ty -> + tb stack_ty -> + ((ta stack_ty, tb stack_ty) eq * ta stack_ty * context) tzresult = + fun ~legacy loc -> + let rec help : + type a b. + context -> + int -> + a stack_ty -> + b stack_ty -> + ((a stack_ty, b stack_ty) eq * a stack_ty * context) tzresult = + fun ctxt lvl stack1 stack2 -> + match (stack1, stack2) with + | (Empty_t, Empty_t) -> + ok (Eq, Empty_t, ctxt) + | (Item_t (ty1, rest1, annot1), Item_t (ty2, rest2, annot2)) -> + merge_types ~legacy ctxt loc ty1 ty2 + |> record_trace (Bad_stack_item lvl) + >>? fun (Eq, ty, ctxt) -> + help ctxt (lvl + 1) rest1 rest2 + >|? fun (Eq, rest, ctxt) -> + let annot = merge_var_annot annot1 annot2 in + ((Eq : (a stack_ty, b stack_ty) eq), Item_t (ty, rest, annot), ctxt) + | (_, _) -> + error Bad_stack_length + in + help + +(* ---- Type checker results -------------------------------------------------*) + +type 'bef judgement = + | Typed : ('bef, 'aft) descr -> 'bef judgement + | Failed : { + descr : 'aft. 'aft stack_ty -> ('bef, 'aft) descr; + } + -> 'bef judgement + +(* ---- Type checker (Untyped expressions -> Typed IR) ----------------------*) + +type ('t, 'f, 'b) branch = { + branch : 'r. ('t, 'r) descr -> ('f, 'r) descr -> ('b, 'r) descr; +} +[@@unboxed] + +let merge_branches : + type bef a b. + legacy:bool -> + context -> + int -> + a judgement -> + b judgement -> + (a, b, bef) branch -> + (bef judgement * context) tzresult = + fun ~legacy ctxt loc btr bfr {branch} -> + match (btr, bfr) with + | (Typed ({aft = aftbt; _} as dbt), Typed ({aft = aftbf; _} as dbf)) -> + let unmatched_branches () = + serialize_stack_for_error ctxt aftbt + >>? fun (aftbt, ctxt) -> + serialize_stack_for_error ctxt aftbf + >|? fun (aftbf, _ctxt) -> Unmatched_branches (loc, aftbt, aftbf) + in + record_trace_eval + unmatched_branches + ( merge_stacks ~legacy loc ctxt 1 aftbt aftbf + >|? fun (Eq, merged_stack, ctxt) -> + ( Typed + (branch {dbt with aft = merged_stack} {dbf with aft = merged_stack}), + ctxt ) ) + | (Failed {descr = descrt}, Failed {descr = descrf}) -> + let descr ret = branch (descrt ret) (descrf ret) in + ok (Failed {descr}, ctxt) + | (Typed dbt, Failed {descr = descrf}) -> + ok (Typed (branch dbt (descrf dbt.aft)), ctxt) + | (Failed {descr = descrt}, Typed dbf) -> + ok (Typed (branch (descrt dbf.aft) dbf), ctxt) + +let parse_memo_size (n : (location, _) Micheline.node) : + Sapling.Memo_size.t tzresult = + match n with + | Int (_, z) -> ( + match Sapling.Memo_size.parse_z z with + | Ok _ as ok_memo_size -> + ok_memo_size + | Error msg -> + error @@ Invalid_syntactic_constant (location n, strip_locations n, msg) + ) + | _ -> + error @@ Invalid_kind (location n, [Int_kind], kind n) + +let rec parse_comparable_ty : + context -> Script.node -> (ex_comparable_ty * context) tzresult = + fun ctxt ty -> + Gas.consume ctxt Typecheck_costs.parse_type_cycle + >>? fun ctxt -> + match ty with + | Prim (loc, T_unit, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Unit_key tname), ctxt) + | Prim (loc, T_never, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Never_key tname), ctxt) + | Prim (loc, T_int, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Int_key tname), ctxt) + | Prim (loc, T_nat, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Nat_key tname), ctxt) + | Prim (loc, T_signature, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Signature_key tname), ctxt) + | Prim (loc, T_string, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (String_key tname), ctxt) + | Prim (loc, T_bytes, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Bytes_key tname), ctxt) + | Prim (loc, T_mutez, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Mutez_key tname), ctxt) + | Prim (loc, T_bool, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Bool_key tname), ctxt) + | Prim (loc, T_key_hash, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Key_hash_key tname), ctxt) + | Prim (loc, T_key, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Key_key tname), ctxt) + | Prim (loc, T_timestamp, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Timestamp_key tname), ctxt) + | Prim (loc, T_chain_id, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Chain_id_key tname), ctxt) + | Prim (loc, T_address, [], annot) -> + parse_type_annot loc annot + >|? fun tname -> (Ex_comparable_ty (Address_key tname), ctxt) + | Prim + ( loc, + ( ( T_unit + | T_never + | T_int + | T_nat + | T_string + | T_bytes + | T_mutez + | T_bool + | T_key_hash + | T_timestamp + | T_address + | T_chain_id + | T_signature + | T_key ) as prim ), + l, + _ ) -> + error (Invalid_arity (loc, prim, 0, List.length l)) + | Prim (loc, T_pair, left :: right, annot) -> + parse_type_annot loc annot + >>? fun pname -> + extract_field_annot left + >>? fun (left, left_annot) -> + ( match right with + | [right] -> + extract_field_annot right + | right -> + (* Unfold [pair t1 ... tn] as [pair t1 (... (pair tn-1 tn))] *) + ok (Prim (loc, T_pair, right, []), None) ) + >>? fun (right, right_annot) -> + parse_comparable_ty ctxt right + >>? fun (Ex_comparable_ty right, ctxt) -> + parse_comparable_ty ctxt left + >|? fun (Ex_comparable_ty left, ctxt) -> + ( Ex_comparable_ty + (Pair_key ((left, left_annot), (right, right_annot), pname)), + ctxt ) + | Prim (loc, T_or, [left; right], annot) -> + parse_type_annot loc annot + >>? fun pname -> + extract_field_annot left + >>? fun (left, left_annot) -> + extract_field_annot right + >>? fun (right, right_annot) -> + parse_comparable_ty ctxt right + >>? fun (Ex_comparable_ty right, ctxt) -> + parse_comparable_ty ctxt left + >|? fun (Ex_comparable_ty left, ctxt) -> + ( Ex_comparable_ty + (Union_key ((left, left_annot), (right, right_annot), pname)), + ctxt ) + | Prim (loc, ((T_pair | T_or) as prim), l, _) -> + error (Invalid_arity (loc, prim, 2, List.length l)) + | Prim (loc, T_option, [t], annot) -> + parse_type_annot loc annot + >>? fun tname -> + parse_comparable_ty ctxt t + >|? fun (Ex_comparable_ty t, ctxt) -> + (Ex_comparable_ty (Option_key (t, tname)), ctxt) + | Prim (loc, T_option, l, _) -> + error (Invalid_arity (loc, T_option, 1, List.length l)) + | Prim + ( loc, + (T_set | T_map | T_list | T_lambda | T_contract | T_operation), + _, + _ ) -> + error (Comparable_type_expected (loc, Micheline.strip_locations ty)) + | expr -> + error + @@ unexpected + expr + [] + Type_namespace + [ T_unit; + T_never; + T_int; + T_nat; + T_string; + T_bytes; + T_mutez; + T_bool; + T_key_hash; + T_timestamp; + T_address; + T_pair; + T_or; + T_option; + T_chain_id; + T_signature; + T_key ] + +and parse_packable_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult = + fun ctxt ~legacy -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage:false + ~allow_operation:false + ~allow_contract:legacy + ~allow_ticket:false + +and parse_parameter_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult = + fun ctxt ~legacy -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage:true + ~allow_operation:false + ~allow_contract:true + ~allow_ticket:true + +and parse_normal_storage_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult = + fun ctxt ~legacy -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage:true + ~allow_operation:false + ~allow_contract:legacy + ~allow_ticket:true + +and parse_any_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult = + fun ctxt ~legacy -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage:true + ~allow_operation:true + ~allow_contract:true + ~allow_ticket:true + +and parse_ty : + context -> + legacy:bool -> + allow_lazy_storage:bool -> + allow_operation:bool -> + allow_contract:bool -> + allow_ticket:bool -> + Script.node -> + (ex_ty * context) tzresult = + fun ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + node -> + Gas.consume ctxt Typecheck_costs.parse_type_cycle + >>? fun ctxt -> + match node with + | Prim (loc, T_unit, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Unit_t ty_name), ctxt) + | Prim (loc, T_int, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Int_t ty_name), ctxt) + | Prim (loc, T_nat, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Nat_t ty_name), ctxt) + | Prim (loc, T_string, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (String_t ty_name), ctxt) + | Prim (loc, T_bytes, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Bytes_t ty_name), ctxt) + | Prim (loc, T_mutez, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Mutez_t ty_name), ctxt) + | Prim (loc, T_bool, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Bool_t ty_name), ctxt) + | Prim (loc, T_key, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Key_t ty_name), ctxt) + | Prim (loc, T_key_hash, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Key_hash_t ty_name), ctxt) + | Prim (loc, T_timestamp, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Timestamp_t ty_name), ctxt) + | Prim (loc, T_address, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Address_t ty_name), ctxt) + | Prim (loc, T_signature, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Signature_t ty_name), ctxt) + | Prim (loc, T_operation, [], annot) -> + if allow_operation then + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Operation_t ty_name), ctxt) + else error (Unexpected_operation loc) + | Prim (loc, T_chain_id, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Chain_id_t ty_name), ctxt) + | Prim (loc, T_never, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Never_t ty_name), ctxt) + | Prim (loc, T_bls12_381_g1, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Bls12_381_g1_t ty_name), ctxt) + | Prim (loc, T_bls12_381_g2, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Bls12_381_g2_t ty_name), ctxt) + | Prim (loc, T_bls12_381_fr, [], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Bls12_381_fr_t ty_name), ctxt) + | Prim (loc, T_contract, [utl], annot) -> + if allow_contract then + parse_parameter_ty ctxt ~legacy utl + >>? fun (Ex_ty tl, ctxt) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Contract_t (tl, ty_name)), ctxt) + else error (Unexpected_contract loc) + | Prim (loc, T_pair, utl :: utr, annot) -> + extract_field_annot utl + >>? fun (utl, left_field) -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + utl + >>? fun (Ex_ty tl, ctxt) -> + ( match utr with + | [utr] -> + extract_field_annot utr + | utr -> + (* Unfold [pair t1 ... tn] as [pair t1 (... (pair tn-1 tn))] *) + ok (Prim (loc, T_pair, utr, []), None) ) + >>? fun (utr, right_field) -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + utr + >>? fun (Ex_ty tr, ctxt) -> + parse_type_annot loc annot + >>? fun ty_name -> + ok + ( Ex_ty + (Pair_t ((tl, left_field, None), (tr, right_field, None), ty_name)), + ctxt ) + | Prim (loc, T_or, [utl; utr], annot) -> + extract_field_annot utl + >>? fun (utl, left_constr) -> + extract_field_annot utr + >>? fun (utr, right_constr) -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + utl + >>? fun (Ex_ty tl, ctxt) -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + utr + >>? fun (Ex_ty tr, ctxt) -> + parse_type_annot loc annot + >>? fun ty_name -> + ok + (Ex_ty (Union_t ((tl, left_constr), (tr, right_constr), ty_name)), ctxt) + | Prim (loc, T_lambda, [uta; utr], annot) -> + parse_any_ty ctxt ~legacy uta + >>? fun (Ex_ty ta, ctxt) -> + parse_any_ty ctxt ~legacy utr + >>? fun (Ex_ty tr, ctxt) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Lambda_t (ta, tr, ty_name)), ctxt) + | Prim (loc, T_option, [ut], annot) -> + ( if legacy then + (* legacy semantics with (broken) field annotations *) + extract_field_annot ut + >>? fun (ut, _some_constr) -> + parse_composed_type_annot loc annot + >>? fun (ty_name, _none_constr, _) -> ok (ut, ty_name) + else parse_type_annot loc annot >>? fun ty_name -> ok (ut, ty_name) ) + >>? fun (ut, ty_name) -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ut + >>? fun (Ex_ty t, ctxt) -> ok (Ex_ty (Option_t (t, ty_name)), ctxt) + | Prim (loc, T_list, [ut], annot) -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ut + >>? fun (Ex_ty t, ctxt) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (List_t (t, ty_name)), ctxt) + | Prim (loc, T_ticket, [ut], annot) -> + if allow_ticket then + parse_comparable_ty ctxt ut + >>? fun (Ex_comparable_ty t, ctxt) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Ticket_t (t, ty_name)), ctxt) + else error (Unexpected_ticket loc) + | Prim (loc, T_set, [ut], annot) -> + parse_comparable_ty ctxt ut + >>? fun (Ex_comparable_ty t, ctxt) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Set_t (t, ty_name)), ctxt) + | Prim (loc, T_map, [uta; utr], annot) -> + parse_comparable_ty ctxt uta + >>? fun (Ex_comparable_ty ta, ctxt) -> + parse_ty + ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + utr + >>? fun (Ex_ty tr, ctxt) -> + parse_type_annot loc annot + >>? fun ty_name -> ok (Ex_ty (Map_t (ta, tr, ty_name)), ctxt) + | Prim (loc, T_sapling_transaction, [memo_size], annot) -> + parse_type_annot loc annot + >>? fun ty_name -> + parse_memo_size memo_size + >|? fun memo_size -> + (Ex_ty (Sapling_transaction_t (memo_size, ty_name)), ctxt) + (* + /!\ When adding new lazy storage kinds, be careful to use + [when allow_lazy_storage] /!\ + Lazy storage should not be packable to avoid stealing a lazy storage + from another contract with `PUSH t id` or `UNPACK`. + *) + | Prim (loc, T_big_map, args, annot) when allow_lazy_storage -> + parse_big_map_ty ctxt ~legacy loc args annot + >>? fun (big_map_ty, ctxt) -> ok (big_map_ty, ctxt) + | Prim (loc, T_sapling_state, [memo_size], annot) when allow_lazy_storage -> + parse_type_annot loc annot + >>? fun ty_name -> + parse_memo_size memo_size + >|? fun memo_size -> (Ex_ty (Sapling_state_t (memo_size, ty_name)), ctxt) + | Prim (loc, (T_big_map | T_sapling_state), _, _) -> + error (Unexpected_lazy_storage loc) + | Prim + ( loc, + ( ( T_unit + | T_signature + | T_int + | T_nat + | T_string + | T_bytes + | T_mutez + | T_bool + | T_key + | T_key_hash + | T_timestamp + | T_address + | T_chain_id + | T_operation + | T_never ) as prim ), + l, + _ ) -> + error (Invalid_arity (loc, prim, 0, List.length l)) + | Prim + (loc, ((T_set | T_list | T_option | T_contract | T_ticket) as prim), l, _) + -> + error (Invalid_arity (loc, prim, 1, List.length l)) + | Prim (loc, ((T_pair | T_or | T_map | T_lambda) as prim), l, _) -> + error (Invalid_arity (loc, prim, 2, List.length l)) + | expr -> + error + @@ unexpected + expr + [] + Type_namespace + [ T_pair; + T_or; + T_set; + T_map; + T_list; + T_option; + T_lambda; + T_unit; + T_signature; + T_contract; + T_int; + T_nat; + T_operation; + T_string; + T_bytes; + T_mutez; + T_bool; + T_key; + T_key_hash; + T_timestamp; + T_chain_id; + T_never; + T_bls12_381_g1; + T_bls12_381_g2; + T_bls12_381_fr; + T_ticket ] + +and parse_big_map_ty ctxt ~legacy big_map_loc args map_annot = + Gas.consume ctxt Typecheck_costs.parse_type_cycle + >>? fun ctxt -> + match args with + | [key_ty; value_ty] -> + parse_comparable_ty ctxt key_ty + >>? fun (Ex_comparable_ty key_ty, ctxt) -> + parse_big_map_value_ty ctxt ~legacy value_ty + >>? fun (Ex_ty value_ty, ctxt) -> + parse_type_annot big_map_loc map_annot + >|? fun map_name -> + let big_map_ty = Big_map_t (key_ty, value_ty, map_name) in + (Ex_ty big_map_ty, ctxt) + | args -> + error @@ Invalid_arity (big_map_loc, T_big_map, 2, List.length args) + +and parse_big_map_value_ty ctxt ~legacy value_ty = + parse_ty + ctxt + ~legacy + ~allow_lazy_storage:false + ~allow_operation:false + ~allow_contract:legacy + ~allow_ticket:true + value_ty + +and parse_storage_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult = + fun ctxt ~legacy node -> + match node with + | Prim + ( loc, + T_pair, + [Prim (big_map_loc, T_big_map, args, map_annot); remaining_storage], + storage_annot ) + when legacy -> ( + match storage_annot with + | [] -> + parse_normal_storage_ty ctxt ~legacy node + | [single] + when Compare.Int.(String.length single > 0) + && Compare.Char.(single.[0] = '%') -> + parse_normal_storage_ty ctxt ~legacy node + | _ -> + (* legacy semantics of big maps used the wrong annotation parser *) + Gas.consume ctxt Typecheck_costs.parse_type_cycle + >>? fun ctxt -> + parse_big_map_ty ctxt ~legacy big_map_loc args map_annot + >>? fun (Ex_ty big_map_ty, ctxt) -> + parse_normal_storage_ty ctxt ~legacy remaining_storage + >>? fun (Ex_ty remaining_storage, ctxt) -> + parse_composed_type_annot loc storage_annot + >>? fun (ty_name, map_field, storage_field) -> + ok + ( Ex_ty + (Pair_t + ( (big_map_ty, map_field, None), + (remaining_storage, storage_field, None), + ty_name )), + ctxt ) ) + | _ -> + parse_normal_storage_ty ctxt ~legacy node + +let check_packable ~legacy loc root = + let rec check : type t. t ty -> unit tzresult = function + (* /!\ When adding new lazy storage kinds, be sure to return an error. /!\ + Lazy storage should not be packable. *) + | Big_map_t _ -> + error (Unexpected_lazy_storage loc) + | Sapling_state_t _ -> + error (Unexpected_lazy_storage loc) + | Operation_t _ -> + error (Unexpected_operation loc) + | Unit_t _ -> + ok_unit + | Int_t _ -> + ok_unit + | Nat_t _ -> + ok_unit + | Signature_t _ -> + ok_unit + | String_t _ -> + ok_unit + | Bytes_t _ -> + ok_unit + | Mutez_t _ -> + ok_unit + | Key_hash_t _ -> + ok_unit + | Key_t _ -> + ok_unit + | Timestamp_t _ -> + ok_unit + | Address_t _ -> + ok_unit + | Bool_t _ -> + ok_unit + | Chain_id_t _ -> + ok_unit + | Never_t _ -> + ok_unit + | Set_t (_, _) -> + ok_unit + | Ticket_t _ -> + error (Unexpected_ticket loc) + | Lambda_t (_, _, _) -> + ok_unit + | Bls12_381_g1_t _ -> + ok_unit + | Bls12_381_g2_t _ -> + ok_unit + | Bls12_381_fr_t _ -> + ok_unit + | Pair_t ((l_ty, _, _), (r_ty, _, _), _) -> + check l_ty >>? fun () -> check r_ty + | Union_t ((l_ty, _), (r_ty, _), _) -> + check l_ty >>? fun () -> check r_ty + | Option_t (v_ty, _) -> + check v_ty + | List_t (elt_ty, _) -> + check elt_ty + | Map_t (_, elt_ty, _) -> + check elt_ty + | Contract_t (_, _) when legacy -> + ok_unit + | Contract_t (_, _) -> + error (Unexpected_contract loc) + | Sapling_transaction_t _ -> + ok () + in + check root + +type ('arg, 'storage) code = { + code : (('arg, 'storage) pair, (operation boxed_list, 'storage) pair) lambda; + arg_type : 'arg ty; + storage_type : 'storage ty; + root_name : field_annot option; +} + +type ex_script = Ex_script : ('a, 'c) script -> ex_script + +type ex_code = Ex_code : ('a, 'c) code -> ex_code + +type _ dig_proof_argument = + | Dig_proof_argument : + ( ('x * 'rest, 'rest, 'bef, 'aft) stack_prefix_preservation_witness + * ('x ty * var_annot option) + * 'aft stack_ty ) + -> 'bef dig_proof_argument + +type (_, _) dug_proof_argument = + | Dug_proof_argument : + ( ('rest, 'x * 'rest, 'bef, 'aft) stack_prefix_preservation_witness + * unit + * 'aft stack_ty ) + -> ('bef, 'x) dug_proof_argument + +type _ dipn_proof_argument = + | Dipn_proof_argument : + ( ('fbef, 'faft, 'bef, 'aft) stack_prefix_preservation_witness + * (context * ('fbef, 'faft) descr) + * 'aft stack_ty ) + -> 'bef dipn_proof_argument + +type _ dropn_proof_argument = + | Dropn_proof_argument : + ( ('rest, 'rest, 'bef, 'aft) stack_prefix_preservation_witness + * 'rest stack_ty + * 'aft stack_ty ) + -> 'bef dropn_proof_argument + +type 'before comb_proof_argument = + | Comb_proof_argument : + ('before, 'after) comb_gadt_witness * 'after stack_ty + -> 'before comb_proof_argument + +type 'before uncomb_proof_argument = + | Uncomb_proof_argument : + ('before, 'after) uncomb_gadt_witness * 'after stack_ty + -> 'before uncomb_proof_argument + +type 'before comb_get_proof_argument = + | Comb_get_proof_argument : + ('before, 'after) comb_get_gadt_witness * 'after ty + -> 'before comb_get_proof_argument + +type ('rest, 'before) comb_set_proof_argument = + | Comb_set_proof_argument : + ('rest, 'before, 'after) comb_set_gadt_witness * 'after ty + -> ('rest, 'before) comb_set_proof_argument + +type 'before dup_n_proof_argument = + | Dup_n_proof_argument : + ('before, 'a) dup_n_gadt_witness * 'a ty + -> 'before dup_n_proof_argument + +let find_entrypoint (type full) (full : full ty) ~root_name entrypoint = + let rec find_entrypoint : + type t. t ty -> string -> (Script.node -> Script.node) * ex_ty = + fun t entrypoint -> + match t with + | Union_t ((tl, al), (tr, ar), _) -> ( + if + match al with + | None -> + false + | Some (Field_annot l) -> + Compare.String.(l = entrypoint) + then ((fun e -> Prim (0, D_Left, [e], [])), Ex_ty tl) + else if + match ar with + | None -> + false + | Some (Field_annot r) -> + Compare.String.(r = entrypoint) + then ((fun e -> Prim (0, D_Right, [e], [])), Ex_ty tr) + else + try + let (f, t) = find_entrypoint tl entrypoint in + ((fun e -> Prim (0, D_Left, [f e], [])), t) + with Not_found -> + let (f, t) = find_entrypoint tr entrypoint in + ((fun e -> Prim (0, D_Right, [f e], [])), t) ) + | _ -> + raise Not_found + in + let entrypoint = + if Compare.String.(entrypoint = "") then "default" else entrypoint + in + if Compare.Int.(String.length entrypoint > 31) then + error (Entrypoint_name_too_long entrypoint) + else + match root_name with + | Some (Field_annot root_name) when Compare.String.(entrypoint = root_name) + -> + ok ((fun e -> e), Ex_ty full) + | _ -> ( + try ok (find_entrypoint full entrypoint) + with Not_found -> ( + match entrypoint with + | "default" -> + ok ((fun e -> e), Ex_ty full) + | _ -> + error (No_such_entrypoint entrypoint) ) ) + +let find_entrypoint_for_type (type full exp) ~legacy ~(full : full ty) + ~(expected : exp ty) ~root_name entrypoint ctxt loc : + (context * string * exp ty) tzresult = + match (entrypoint, root_name) with + | ("default", Some (Field_annot "root")) -> ( + match find_entrypoint full ~root_name entrypoint with + | Error _ as err -> + err + | Ok (_, Ex_ty ty) -> ( + match merge_types ~legacy ctxt loc ty expected with + | Ok (Eq, ty, ctxt) -> + ok (ctxt, "default", ty) + | Error _ -> + merge_types ~legacy ctxt loc full expected + >>? fun (Eq, full, ctxt) -> ok (ctxt, "root", (full : exp ty)) ) ) + | _ -> + find_entrypoint full ~root_name entrypoint + >>? fun (_, Ex_ty ty) -> + merge_types ~legacy ctxt loc ty expected + >>? fun (Eq, ty, ctxt) -> ok (ctxt, entrypoint, (ty : exp ty)) + +module Entrypoints = Set.Make (String) + +exception Duplicate of string + +exception Too_long of string + +let well_formed_entrypoints (type full) (full : full ty) ~root_name = + let merge path annot (type t) (ty : t ty) reachable + ((first_unreachable, all) as acc) = + match annot with + | None | Some (Field_annot "") -> ( + if reachable then acc + else + match ty with + | Union_t _ -> + acc + | _ -> ( + match first_unreachable with + | None -> + (Some (List.rev path), all) + | Some _ -> + acc ) ) + | Some (Field_annot name) -> + if Compare.Int.(String.length name > 31) then raise (Too_long name) + else if Entrypoints.mem name all then raise (Duplicate name) + else (first_unreachable, Entrypoints.add name all) + in + let rec check : + type t. + t ty -> + prim list -> + bool -> + prim list option * Entrypoints.t -> + prim list option * Entrypoints.t = + fun t path reachable acc -> + match t with + | Union_t ((tl, al), (tr, ar), _) -> + let acc = merge (D_Left :: path) al tl reachable acc in + let acc = merge (D_Right :: path) ar tr reachable acc in + let acc = + check + tl + (D_Left :: path) + (match al with Some _ -> true | None -> reachable) + acc + in + check + tr + (D_Right :: path) + (match ar with Some _ -> true | None -> reachable) + acc + | _ -> + acc + in + try + let (init, reachable) = + match root_name with + | None | Some (Field_annot "") -> + (Entrypoints.empty, false) + | Some (Field_annot name) -> + (Entrypoints.singleton name, true) + in + let (first_unreachable, all) = check full [] reachable (None, init) in + if not (Entrypoints.mem "default" all) then ok_unit + else + match first_unreachable with + | None -> + ok_unit + | Some path -> + error (Unreachable_entrypoint path) + with + | Duplicate name -> + error (Duplicate_entrypoint name) + | Too_long name -> + error (Entrypoint_name_too_long name) + +let parse_uint ~nb_bits = + assert (Compare.Int.(nb_bits >= 0 && nb_bits <= 30)) ; + let max_int = (1 lsl nb_bits) - 1 in + let max_z = Z.of_int max_int in + function + | Micheline.Int (_, n) when Compare.Z.(Z.zero <= n) && Compare.Z.(n <= max_z) + -> + ok (Z.to_int n) + | node -> + error + @@ Invalid_syntactic_constant + ( location node, + strip_locations node, + "a positive " ^ string_of_int nb_bits + ^ "-bit integer (between 0 and " ^ string_of_int max_int ^ ")" ) + +let parse_uint10 = parse_uint ~nb_bits:10 + +let parse_uint11 = parse_uint ~nb_bits:11 + +(* This type is used to: + - serialize and deserialize tickets when they are stored or transferred, + - type the READ_TICKET instruction. *) +let opened_ticket_type ty = + Pair_key + ( (Address_key None, None), + (Pair_key ((ty, None), (Nat_key None, None), None), None), + None ) + +(* -- parse data of primitive types -- *) + +let parse_unit ctxt ~legacy = function + | Prim (loc, D_Unit, [], annot) -> + (if legacy then ok_unit else error_unexpected_annot loc annot) + >>? fun () -> + Gas.consume ctxt Typecheck_costs.unit >|? fun ctxt -> ((), ctxt) + | Prim (loc, D_Unit, l, _) -> + error @@ Invalid_arity (loc, D_Unit, 0, List.length l) + | expr -> + error @@ unexpected expr [] Constant_namespace [D_Unit] + +let parse_bool ctxt ~legacy = function + | Prim (loc, D_True, [], annot) -> + (if legacy then ok_unit else error_unexpected_annot loc annot) + >>? fun () -> + Gas.consume ctxt Typecheck_costs.bool >|? fun ctxt -> (true, ctxt) + | Prim (loc, D_False, [], annot) -> + (if legacy then ok_unit else error_unexpected_annot loc annot) + >>? fun () -> + Gas.consume ctxt Typecheck_costs.bool >|? fun ctxt -> (false, ctxt) + | Prim (loc, ((D_True | D_False) as c), l, _) -> + error @@ Invalid_arity (loc, c, 0, List.length l) + | expr -> + error @@ unexpected expr [] Constant_namespace [D_True; D_False] + +let parse_string ctxt = function + | String (loc, v) as expr -> + Gas.consume ctxt (Typecheck_costs.check_printable v) + >>? fun ctxt -> + let rec check_printable_ascii i = + if Compare.Int.(i < 0) then true + else + match v.[i] with + | '\n' | '\x20' .. '\x7E' -> + check_printable_ascii (i - 1) + | _ -> + false + in + if check_printable_ascii (String.length v - 1) then ok (v, ctxt) + else + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a printable ascii string") + | expr -> + error @@ Invalid_kind (location expr, [String_kind], kind expr) + +let parse_bytes ctxt = function + | Bytes (_, v) -> + ok (v, ctxt) + | expr -> + error @@ Invalid_kind (location expr, [Bytes_kind], kind expr) + +let parse_int ctxt = function + | Int (_, v) -> + ok (Script_int.of_zint v, ctxt) + | expr -> + error @@ Invalid_kind (location expr, [Int_kind], kind expr) + +let parse_nat ctxt = function + | Int (loc, v) as expr -> ( + let v = Script_int.of_zint v in + match Script_int.is_nat v with + | Some nat -> + ok (nat, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a non-negative integer") ) + | expr -> + error @@ Invalid_kind (location expr, [Int_kind], kind expr) + +let parse_mutez ctxt = function + | Int (loc, v) as expr -> ( + try + match Tez.of_mutez (Z.to_int64 v) with + | None -> + raise Exit + | Some tez -> + ok (tez, ctxt) + with _ -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid mutez amount") ) + | expr -> + error @@ Invalid_kind (location expr, [Int_kind], kind expr) + +let parse_timestamp ctxt = function + | Int (_, v) (* As unparsed with [Optimized] or out of bounds [Readable]. *) + -> + ok (Script_timestamp.of_zint v, ctxt) + | String (loc, s) as expr (* As unparsed with [Readable]. *) -> ( + Gas.consume ctxt Typecheck_costs.timestamp_readable + >>? fun ctxt -> + match Script_timestamp.of_string s with + | Some v -> + ok (v, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid timestamp") ) + | expr -> + error @@ Invalid_kind (location expr, [String_kind; Int_kind], kind expr) + +let parse_key ctxt = function + | Bytes (loc, bytes) as expr -> ( + (* As unparsed with [Optimized]. *) + Gas.consume ctxt Typecheck_costs.public_key_optimized + >>? fun ctxt -> + match + Data_encoding.Binary.of_bytes Signature.Public_key.encoding bytes + with + | Some k -> + ok (k, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid public key") ) + | String (loc, s) as expr -> ( + (* As unparsed with [Readable]. *) + Gas.consume ctxt Typecheck_costs.public_key_readable + >>? fun ctxt -> + match Signature.Public_key.of_b58check_opt s with + | Some k -> + ok (k, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid public key") ) + | expr -> + error + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_key_hash ctxt = function + | Bytes (loc, bytes) as expr -> ( + (* As unparsed with [Optimized]. *) + Gas.consume ctxt Typecheck_costs.key_hash_optimized + >>? fun ctxt -> + match + Data_encoding.Binary.of_bytes Signature.Public_key_hash.encoding bytes + with + | Some k -> + ok (k, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid key hash") ) + | String (loc, s) as expr (* As unparsed with [Readable]. *) -> ( + Gas.consume ctxt Typecheck_costs.key_hash_readable + >>? fun ctxt -> + match Signature.Public_key_hash.of_b58check_opt s with + | Some k -> + ok (k, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid key hash") ) + | expr -> + error + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_signature ctxt = function + | Bytes (loc, bytes) as expr (* As unparsed with [Optimized]. *) -> ( + Gas.consume ctxt Typecheck_costs.signature_optimized + >>? fun ctxt -> + match Data_encoding.Binary.of_bytes Signature.encoding bytes with + | Some k -> + ok (k, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid signature") ) + | String (loc, s) as expr (* As unparsed with [Readable]. *) -> ( + Gas.consume ctxt Typecheck_costs.signature_readable + >>? fun ctxt -> + match Signature.of_b58check_opt s with + | Some s -> + ok (s, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid signature") ) + | expr -> + error + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_chain_id ctxt = function + | Bytes (loc, bytes) as expr -> ( + Gas.consume ctxt Typecheck_costs.chain_id_optimized + >>? fun ctxt -> + match Data_encoding.Binary.of_bytes Chain_id.encoding bytes with + | Some k -> + ok (k, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid chain id") ) + | String (loc, s) as expr -> ( + Gas.consume ctxt Typecheck_costs.chain_id_readable + >>? fun ctxt -> + match Chain_id.of_b58check_opt s with + | Some s -> + ok (s, ctxt) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid chain id") ) + | expr -> + error + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_address ctxt = function + | Bytes (loc, bytes) as expr (* As unparsed with [Optimized]. *) -> ( + Gas.consume ctxt Typecheck_costs.contract + >>? fun ctxt -> + match + Data_encoding.Binary.of_bytes + Data_encoding.(tup2 Contract.encoding Variable.string) + bytes + with + | Some (c, entrypoint) -> ( + if Compare.Int.(String.length entrypoint > 31) then + error (Entrypoint_name_too_long entrypoint) + else + match entrypoint with + | "" -> + ok ((c, "default"), ctxt) + | "default" -> + error (Unexpected_annotation loc) + | name -> + ok ((c, name), ctxt) ) + | None -> + error + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid address") ) + | String (loc, s) (* As unparsed with [Readable]. *) -> + Gas.consume ctxt Typecheck_costs.contract + >>? fun ctxt -> + ( match String.index_opt s '%' with + | None -> + ok (s, "default") + | Some pos -> ( + let len = String.length s - pos - 1 in + let name = String.sub s (pos + 1) len in + if Compare.Int.(len > 31) then error (Entrypoint_name_too_long name) + else + match (String.sub s 0 pos, name) with + | (addr, "") -> + ok (addr, "default") + | (_, "default") -> + error @@ Unexpected_annotation loc + | addr_and_name -> + ok addr_and_name ) ) + >>? fun (addr, entrypoint) -> + Contract.of_b58check addr >|? fun c -> ((c, entrypoint), ctxt) + | expr -> + error + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_never expr = error @@ Invalid_never_expr (location expr) + +(* -- parse data of complex types -- *) + +let parse_pair (type r) parse_l parse_r ctxt ~legacy + (r_comb_witness : (r, unit -> _) comb_witness) expr = + let parse_comb loc l rs = + parse_l ctxt l + >>=? fun (l, ctxt) -> + ( match (rs, r_comb_witness) with + | ([r], _) -> + ok r + | ([], _) -> + error @@ Invalid_arity (loc, D_Pair, 2, 1) + | (_ :: _, Comb_Pair _) -> + (* Unfold [Pair x1 ... xn] as [Pair x1 (Pair x2 ... xn-1 xn))] + for type [pair ta (pair tb1 tb2)] and n >= 3 only *) + ok (Prim (loc, D_Pair, rs, [])) + | _ -> + error @@ Invalid_arity (loc, D_Pair, 2, 1 + List.length rs) ) + >>?= fun r -> parse_r ctxt r >|=? fun (r, ctxt) -> ((l, r), ctxt) + in + match expr with + | Prim (loc, D_Pair, l :: rs, annot) -> + (if legacy then ok_unit else error_unexpected_annot loc annot) + >>?= fun () -> parse_comb loc l rs + | Prim (loc, D_Pair, l, _) -> + fail @@ Invalid_arity (loc, D_Pair, 2, List.length l) + (* Unfold [{x1; ...; xn}] as [Pair x1 x2 ... xn-1 xn] for n >= 2 *) + | Seq (loc, l :: (_ :: _ as rs)) -> + parse_comb loc l rs + | Seq (loc, l) -> + fail @@ Invalid_seq_arity (loc, 2, List.length l) + | expr -> + fail @@ unexpected expr [] Constant_namespace [D_Pair] + +let parse_union parse_l parse_r ctxt ~legacy = function + | Prim (loc, D_Left, [v], annot) -> + (if legacy then ok_unit else error_unexpected_annot loc annot) + >>?= fun () -> parse_l ctxt v >|=? fun (v, ctxt) -> (L v, ctxt) + | Prim (loc, D_Left, l, _) -> + fail @@ Invalid_arity (loc, D_Left, 1, List.length l) + | Prim (loc, D_Right, [v], annot) -> + (if legacy then ok_unit else error_unexpected_annot loc annot) + >>?= fun () -> parse_r ctxt v >|=? fun (v, ctxt) -> (R v, ctxt) + | Prim (loc, D_Right, l, _) -> + fail @@ Invalid_arity (loc, D_Right, 1, List.length l) + | expr -> + fail @@ unexpected expr [] Constant_namespace [D_Left; D_Right] + +let parse_option parse_v ctxt ~legacy = function + | Prim (loc, D_Some, [v], annot) -> + (if legacy then ok_unit else error_unexpected_annot loc annot) + >>?= fun () -> parse_v ctxt v >|=? fun (v, ctxt) -> (Some v, ctxt) + | Prim (loc, D_Some, l, _) -> + fail @@ Invalid_arity (loc, D_Some, 1, List.length l) + | Prim (loc, D_None, [], annot) -> + Lwt.return + ( (if legacy then ok_unit else error_unexpected_annot loc annot) + >|? fun () -> (None, ctxt) ) + | Prim (loc, D_None, l, _) -> + fail @@ Invalid_arity (loc, D_None, 0, List.length l) + | expr -> + fail @@ unexpected expr [] Constant_namespace [D_Some; D_None] + +(* -- parse data of comparable types -- *) + +let comparable_comb_witness1 : + type t. t comparable_ty -> (t, unit -> unit) comb_witness = function + | Pair_key _ -> + Comb_Pair Comb_Any + | _ -> + Comb_Any + +let rec parse_comparable_data : + type a. + ?type_logger:type_logger -> + context -> + a comparable_ty -> + Script.node -> + (a * context) tzresult Lwt.t = + fun ?type_logger ctxt ty script_data -> + (* No need for stack_depth here. Unlike [parse_data], + [parse_comparable_data] doesn't call [parse_returning]. + The stack depth is bounded by the type depth, bounded by 1024. *) + let parse_data_error () = + serialize_ty_for_error ctxt (ty_of_comparable_ty ty) + >|? fun (ty, _ctxt) -> + Invalid_constant (location script_data, strip_locations script_data, ty) + in + let traced_no_lwt body = record_trace_eval parse_data_error body in + let traced body = + trace_eval (fun () -> Lwt.return @@ parse_data_error ()) body + in + Gas.consume ctxt Typecheck_costs.parse_data_cycle + (* We could have a smaller cost but let's keep it consistent with + [parse_data] for now. *) + >>?= fun ctxt -> + let legacy = false in + match (ty, script_data) with + | (Unit_key _, expr) -> + Lwt.return @@ traced_no_lwt + @@ (parse_unit ctxt ~legacy expr : (a * context) tzresult) + | (Bool_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_bool ctxt ~legacy expr + | (String_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_string ctxt expr + | (Bytes_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_bytes ctxt expr + | (Int_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_int ctxt expr + | (Nat_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_nat ctxt expr + | (Mutez_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_mutez ctxt expr + | (Timestamp_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_timestamp ctxt expr + | (Key_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_key ctxt expr + | (Key_hash_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_key_hash ctxt expr + | (Signature_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_signature ctxt expr + | (Chain_id_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_chain_id ctxt expr + | (Address_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_address ctxt expr + | (Pair_key ((tl, _), (tr, _), _), expr) -> + let r_witness = comparable_comb_witness1 tr in + let parse_l ctxt v = parse_comparable_data ?type_logger ctxt tl v in + let parse_r ctxt v = parse_comparable_data ?type_logger ctxt tr v in + traced @@ parse_pair parse_l parse_r ctxt ~legacy r_witness expr + | (Union_key ((tl, _), (tr, _), _), expr) -> + let parse_l ctxt v = parse_comparable_data ?type_logger ctxt tl v in + let parse_r ctxt v = parse_comparable_data ?type_logger ctxt tr v in + traced @@ parse_union parse_l parse_r ctxt ~legacy expr + | (Option_key (t, _), expr) -> + let parse_v ctxt v = parse_comparable_data ?type_logger ctxt t v in + traced @@ parse_option parse_v ctxt ~legacy expr + | (Never_key _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_never expr + +(* -- parse data of any type -- *) + +let comb_witness1 : type t. t ty -> (t, unit -> unit) comb_witness = function + | Pair_t _ -> + Comb_Pair Comb_Any + | _ -> + Comb_Any + +(* + Some values, such as operations, tickets, or big map ids, are used only + internally and are not allowed to be forged by users. + In [parse_data], [allow_forged] should be [false] for: + - PUSH + - UNPACK + - user-provided script parameters + - storage on origination + And [true] for: + - internal calls parameters + - storage after origination +*) + +let rec parse_data : + type a. + ?type_logger:type_logger -> + stack_depth:int -> + context -> + legacy:bool -> + allow_forged:bool -> + a ty -> + Script.node -> + (a * context) tzresult Lwt.t = + fun ?type_logger ~stack_depth ctxt ~legacy ~allow_forged ty script_data -> + Gas.consume ctxt Typecheck_costs.parse_data_cycle + >>?= fun ctxt -> + let non_terminal_recursion ?type_logger ctxt ~legacy ty script_data = + if Compare.Int.(stack_depth > 10_000) then + fail Typechecking_too_many_recursive_calls + else + parse_data + ?type_logger + ~stack_depth:(stack_depth + 1) + ctxt + ~legacy + ~allow_forged + ty + script_data + in + let parse_data_error () = + serialize_ty_for_error ctxt ty + >|? fun (ty, _ctxt) -> + Invalid_constant (location script_data, strip_locations script_data, ty) + in + let fail_parse_data () = parse_data_error () >>?= fail in + let traced_no_lwt body = record_trace_eval parse_data_error body in + let traced body = + trace_eval (fun () -> Lwt.return @@ parse_data_error ()) body + in + let traced_fail err = Lwt.return @@ traced_no_lwt (error err) in + let parse_items ?type_logger ctxt expr key_type value_type items item_wrapper + = + fold_left_s + (fun (last_value, map, ctxt) item -> + match item with + | Prim (loc, D_Elt, [k; v], annot) -> + (if legacy then ok_unit else error_unexpected_annot loc annot) + >>?= fun () -> + parse_comparable_data ?type_logger ctxt key_type k + >>=? fun (k, ctxt) -> + non_terminal_recursion ?type_logger ctxt ~legacy value_type v + >>=? fun (v, ctxt) -> + Lwt.return + ( ( match last_value with + | Some value -> + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.compare + key_type + value + k) + >>? fun ctxt -> + let c = compare_comparable key_type value k in + if Compare.Int.(0 <= c) then + if Compare.Int.(0 = c) then + error (Duplicate_map_keys (loc, strip_locations expr)) + else + error (Unordered_map_keys (loc, strip_locations expr)) + else ok ctxt + | None -> + ok ctxt ) + >>? fun ctxt -> + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.map_update k map) + >|? fun ctxt -> + (Some k, map_update k (Some (item_wrapper v)) map, ctxt) ) + | Prim (loc, D_Elt, l, _) -> + fail @@ Invalid_arity (loc, D_Elt, 2, List.length l) + | Prim (loc, name, _, _) -> + fail @@ Invalid_primitive (loc, [D_Elt], name) + | Int _ | String _ | Bytes _ | Seq _ -> + fail_parse_data ()) + (None, empty_map key_type, ctxt) + items + |> traced + >|=? fun (_, items, ctxt) -> (items, ctxt) + in + let parse_big_map_items (type t) ?type_logger ctxt expr + (key_type : t comparable_ty) value_type items item_wrapper = + fold_left_s + (fun (last_key, {map; size}, ctxt) item -> + match item with + | Prim (loc, D_Elt, [k; v], annot) -> + (if legacy then ok_unit else error_unexpected_annot loc annot) + >>?= fun () -> + parse_comparable_data ?type_logger ctxt key_type k + >>=? fun (k, ctxt) -> + hash_comparable_data ctxt key_type k + >>=? fun (key_hash, ctxt) -> + non_terminal_recursion ?type_logger ctxt ~legacy value_type v + >>=? fun (v, ctxt) -> + Lwt.return + ( ( match last_key with + | Some last_key -> + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.compare + key_type + last_key + k) + >>? fun ctxt -> + let c = compare_comparable key_type last_key k in + if Compare.Int.(0 <= c) then + if Compare.Int.(0 = c) then + error (Duplicate_map_keys (loc, strip_locations expr)) + else + error (Unordered_map_keys (loc, strip_locations expr)) + else ok ctxt + | None -> + ok ctxt ) + >>? fun ctxt -> + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.big_map_update + {map; size}) + >>? fun ctxt -> + if Big_map_overlay.mem key_hash map then + error (Duplicate_map_keys (loc, strip_locations expr)) + else + ok + ( Some k, + { + map = Big_map_overlay.add key_hash (k, item_wrapper v) map; + size = size + 1; + }, + ctxt ) ) + | Prim (loc, D_Elt, l, _) -> + fail @@ Invalid_arity (loc, D_Elt, 2, List.length l) + | Prim (loc, name, _, _) -> + fail @@ Invalid_primitive (loc, [D_Elt], name) + | Int _ | String _ | Bytes _ | Seq _ -> + fail_parse_data ()) + (None, {map = Big_map_overlay.empty; size = 0}, ctxt) + items + |> traced + >|=? fun (_, map, ctxt) -> (map, ctxt) + in + match (ty, script_data) with + | (Unit_t _, expr) -> + Lwt.return @@ traced_no_lwt + @@ (parse_unit ctxt ~legacy expr : (a * context) tzresult) + | (Bool_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_bool ctxt ~legacy expr + | (String_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_string ctxt expr + | (Bytes_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_bytes ctxt expr + | (Int_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_int ctxt expr + | (Nat_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_nat ctxt expr + | (Mutez_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_mutez ctxt expr + | (Timestamp_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_timestamp ctxt expr + | (Key_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_key ctxt expr + | (Key_hash_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_key_hash ctxt expr + | (Signature_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_signature ctxt expr + | (Operation_t _, _) -> + (* operations cannot appear in parameters or storage, + the protocol should never parse the bytes of an operation *) + assert false + | (Chain_id_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_chain_id ctxt expr + | (Address_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_address ctxt expr + | (Contract_t (ty, _), expr) -> + traced + ( parse_address ctxt expr + >>?= fun ((c, entrypoint), ctxt) -> + let loc = location expr in + parse_contract ~legacy ctxt loc ty c ~entrypoint + >|=? fun (ctxt, _) -> ((ty, (c, entrypoint)), ctxt) ) + (* Pairs *) + | (Pair_t ((tl, _, _), (tr, _, _), _), expr) -> + let r_witness = comb_witness1 tr in + let parse_l ctxt v = + non_terminal_recursion ?type_logger ctxt ~legacy tl v + in + let parse_r ctxt v = + non_terminal_recursion ?type_logger ctxt ~legacy tr v + in + traced @@ parse_pair parse_l parse_r ctxt ~legacy r_witness expr + (* Unions *) + | (Union_t ((tl, _), (tr, _), _), expr) -> + let parse_l ctxt v = + non_terminal_recursion ?type_logger ctxt ~legacy tl v + in + let parse_r ctxt v = + non_terminal_recursion ?type_logger ctxt ~legacy tr v + in + traced @@ parse_union parse_l parse_r ctxt ~legacy expr + (* Lambdas *) + | (Lambda_t (ta, tr, _ty_name), (Seq (_loc, _) as script_instr)) -> + traced + @@ parse_returning + Lambda + ?type_logger + ~stack_depth + ctxt + ~legacy + (ta, Some (Var_annot "@arg")) + tr + script_instr + | (Lambda_t _, expr) -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + (* Options *) + | (Option_t (t, _), expr) -> + let parse_v ctxt v = + non_terminal_recursion ?type_logger ctxt ~legacy t v + in + traced @@ parse_option parse_v ctxt ~legacy expr + (* Lists *) + | (List_t (t, _ty_name), Seq (_loc, items)) -> + traced + @@ fold_right_s + (fun v (rest, ctxt) -> + non_terminal_recursion ?type_logger ctxt ~legacy t v + >|=? fun (v, ctxt) -> (list_cons v rest, ctxt)) + items + (list_empty, ctxt) + | (List_t _, expr) -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + (* Tickets *) + | (Ticket_t (t, _ty_name), expr) -> + if allow_forged then + parse_comparable_data ?type_logger ctxt (opened_ticket_type t) expr + >|=? fun ((ticketer, (contents, amount)), ctxt) -> + ({ticketer; contents; amount}, ctxt) + else traced_fail (Unexpected_forged_value (location expr)) + (* Sets *) + | (Set_t (t, _ty_name), (Seq (loc, vs) as expr)) -> + traced + @@ fold_left_s + (fun (last_value, set, ctxt) v -> + parse_comparable_data ?type_logger ctxt t v + >>=? fun (v, ctxt) -> + Lwt.return + ( ( match last_value with + | Some value -> + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.compare t value v) + >>? fun ctxt -> + let c = compare_comparable t value v in + if Compare.Int.(0 <= c) then + if Compare.Int.(0 = c) then + error + (Duplicate_set_values (loc, strip_locations expr)) + else + error + (Unordered_set_values (loc, strip_locations expr)) + else ok ctxt + | None -> + ok ctxt ) + >>? fun ctxt -> + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.set_update v set) + >|? fun ctxt -> (Some v, set_update v true set, ctxt) )) + (None, empty_set t, ctxt) + vs + >|=? fun (_, set, ctxt) -> (set, ctxt) + | (Set_t _, expr) -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + (* Maps *) + | (Map_t (tk, tv, _ty_name), (Seq (_, vs) as expr)) -> + parse_items ?type_logger ctxt expr tk tv vs (fun x -> x) + | (Map_t _, expr) -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + | (Big_map_t (tk, tv, _ty_name), expr) -> + ( match expr with + | Int (loc, id) -> + return (Some (id, loc), {map = Big_map_overlay.empty; size = 0}, ctxt) + | Seq (_, vs) -> + parse_big_map_items ?type_logger ctxt expr tk tv vs (fun x -> Some x) + >|=? fun (diff, ctxt) -> (None, diff, ctxt) + | Prim (loc, D_Pair, [Int (loc_id, id); Seq (_, vs)], annot) -> + error_unexpected_annot loc annot + >>?= fun () -> + let tv_opt = Option_t (tv, None) in + parse_big_map_items ?type_logger ctxt expr tk tv_opt vs (fun x -> x) + >|=? fun (diff, ctxt) -> (Some (id, loc_id), diff, ctxt) + | Prim (_, D_Pair, [Int _; expr], _) -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + | Prim (_, D_Pair, [expr; _], _) -> + traced_fail (Invalid_kind (location expr, [Int_kind], kind expr)) + | Prim (loc, D_Pair, l, _) -> + traced_fail @@ Invalid_arity (loc, D_Pair, 2, List.length l) + | _ -> + traced_fail + (unexpected expr [Seq_kind; Int_kind] Constant_namespace [D_Pair]) + ) + >>=? fun (id_opt, diff, ctxt) -> + ( match id_opt with + | None -> + return @@ (None, ctxt) + | Some (id, loc) -> + if allow_forged then + let id = Big_map.Id.parse_z id in + Big_map.exists ctxt id + >>=? function + | (_, None) -> + traced_fail (Invalid_big_map (loc, id)) + | (ctxt, Some (btk, btv)) -> + Lwt.return + ( parse_comparable_ty ctxt (Micheline.root btk) + >>? fun (Ex_comparable_ty btk, ctxt) -> + parse_big_map_value_ty ctxt ~legacy (Micheline.root btv) + >>? fun (Ex_ty btv, ctxt) -> + comparable_ty_eq ctxt tk btk + >>? fun (Eq, ctxt) -> + ty_eq ctxt loc tv btv >>? fun (Eq, ctxt) -> ok (Some id, ctxt) + ) + else traced_fail (Unexpected_forged_value loc) ) + >|=? fun (id, ctxt) -> ({id; diff; key_type = tk; value_type = tv}, ctxt) + | (Never_t _, expr) -> + Lwt.return @@ traced_no_lwt @@ parse_never expr + (* Bls12_381 types *) + | (Bls12_381_g1_t _, Bytes (_, bs)) -> ( + Gas.consume ctxt Typecheck_costs.bls12_381_g1 + >>?= fun ctxt -> + match Bls12_381.G1.of_bytes_opt bs with + | Some pt -> + return (pt, ctxt) + | None -> + fail_parse_data () ) + | (Bls12_381_g1_t _, expr) -> + traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + | (Bls12_381_g2_t _, Bytes (_, bs)) -> ( + Gas.consume ctxt Typecheck_costs.bls12_381_g2 + >>?= fun ctxt -> + match Bls12_381.G2.of_bytes_opt bs with + | Some pt -> + return (pt, ctxt) + | None -> + fail_parse_data () ) + | (Bls12_381_g2_t _, expr) -> + traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + | (Bls12_381_fr_t _, Bytes (_, bs)) -> ( + Gas.consume ctxt Typecheck_costs.bls12_381_fr + >>?= fun ctxt -> + match Bls12_381.Fr.of_bytes_opt bs with + | Some pt -> + return (pt, ctxt) + | None -> + fail_parse_data () ) + | (Bls12_381_fr_t _, Int (_, v)) -> + Gas.consume ctxt Typecheck_costs.bls12_381_fr + >>?= fun ctxt -> return (Bls12_381.Fr.of_z v, ctxt) + | (Bls12_381_fr_t _, expr) -> + traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + (* + /!\ When adding new lazy storage kinds, you may want to guard the parsing + of identifiers with [allow_forged]. + *) + (* Sapling *) + | (Sapling_transaction_t (memo_size, _), Bytes (_, bytes)) -> ( + match Data_encoding.Binary.of_bytes Sapling.transaction_encoding bytes with + | Some transaction -> ( + match Sapling.transaction_get_memo_size transaction with + | None -> + return (transaction, ctxt) + | Some transac_memo_size -> + Lwt.return + ( merge_memo_sizes memo_size transac_memo_size + >|? fun _ms -> (transaction, ctxt) ) ) + | None -> + fail_parse_data () ) + | (Sapling_transaction_t _, expr) -> + traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + | (Sapling_state_t (memo_size, _), Int (loc, id)) -> + if allow_forged then + let id = Sapling.Id.parse_z id in + Sapling.state_from_id ctxt id + >>=? fun (state, ctxt) -> + Lwt.return + ( traced_no_lwt @@ merge_memo_sizes memo_size state.Sapling.memo_size + >|? fun _memo_size -> (state, ctxt) ) + else traced_fail (Unexpected_forged_value loc) + | (Sapling_state_t (memo_size, _), Seq (_, [])) -> + return (Sapling.empty_state ~memo_size (), ctxt) + | (Sapling_state_t _, expr) -> + (* Do not allow to input diffs as they are untrusted and may not be the + result of a verify_update. *) + traced_fail + (Invalid_kind (location expr, [Int_kind; Seq_kind], kind expr)) + +and parse_returning : + type arg ret. + ?type_logger:type_logger -> + stack_depth:int -> + tc_context -> + context -> + legacy:bool -> + arg ty * var_annot option -> + ret ty -> + Script.node -> + ((arg, ret) lambda * context) tzresult Lwt.t = + fun ?type_logger + ~stack_depth + tc_context + ctxt + ~legacy + (arg, arg_annot) + ret + script_instr -> + parse_instr + ?type_logger + tc_context + ctxt + ~legacy + ~stack_depth:(stack_depth + 1) + script_instr + (Item_t (arg, Empty_t, arg_annot)) + >>=? function + | (Typed ({loc; aft = Item_t (ty, Empty_t, _) as stack_ty; _} as descr), ctxt) + -> + Lwt.return + @@ record_trace_eval + (fun () -> + serialize_ty_for_error ctxt ret + >>? fun (ret, ctxt) -> + serialize_stack_for_error ctxt stack_ty + >|? fun (stack_ty, _ctxt) -> Bad_return (loc, stack_ty, ret)) + ( merge_types ~legacy ctxt loc ty ret + >|? fun (Eq, _ret, ctxt) -> + ((Lam (descr, script_instr) : (arg, ret) lambda), ctxt) ) + | (Typed {loc; aft = stack_ty; _}, ctxt) -> + Lwt.return + ( serialize_ty_for_error ctxt ret + >>? fun (ret, ctxt) -> + serialize_stack_for_error ctxt stack_ty + >>? fun (stack_ty, _ctxt) -> error (Bad_return (loc, stack_ty, ret)) ) + | (Failed {descr}, ctxt) -> + return + ( ( Lam (descr (Item_t (ret, Empty_t, None)), script_instr) + : (arg, ret) lambda ), + ctxt ) + +and parse_instr : + type bef. + ?type_logger:type_logger -> + stack_depth:int -> + tc_context -> + context -> + legacy:bool -> + Script.node -> + bef stack_ty -> + (bef judgement * context) tzresult Lwt.t = + fun ?type_logger ~stack_depth tc_context ctxt ~legacy script_instr stack_ty -> + let check_item_ty (type a b) ctxt (exp : a ty) (got : b ty) loc name n m : + ((a, b) eq * a ty * context) tzresult = + record_trace_eval (fun () -> + serialize_stack_for_error ctxt stack_ty + >|? fun (stack_ty, _ctxt) -> Bad_stack (loc, name, m, stack_ty)) + @@ record_trace + (Bad_stack_item n) + ( merge_types ~legacy ctxt loc exp got + >>? fun (Eq, ty, ctxt) -> ok ((Eq : (a, b) eq), (ty : a ty), ctxt) ) + in + let log_stack ctxt loc stack_ty aft = + match (type_logger, script_instr) with + | (None, _) | (Some _, (Seq (-1, _) | Int _ | String _ | Bytes _)) -> + ok_unit + | (Some log, (Prim _ | Seq _)) -> + (* Unparsing for logging done in an unlimited context as this + is used only by the client and not the protocol *) + let ctxt = Gas.set_unlimited ctxt in + unparse_stack ctxt stack_ty + >>? fun (stack_ty, _) -> + unparse_stack ctxt aft >|? fun (aft, _) -> log loc stack_ty aft ; () + in + let return_no_lwt : + type bef. context -> bef judgement -> (bef judgement * context) tzresult + = + fun ctxt judgement -> + match judgement with + | Typed {instr; loc; aft; _} -> + let maximum_type_size = Constants.michelson_maximum_type_size ctxt in + let type_size = + type_size_of_stack_head + aft + ~up_to:(number_of_generated_growing_types instr) + in + if Compare.Int.(type_size > maximum_type_size) then + error (Type_too_large (loc, type_size, maximum_type_size)) + else ok (judgement, ctxt) + | Failed _ -> + ok (judgement, ctxt) + in + let return : + type bef. + context -> bef judgement -> (bef judgement * context) tzresult Lwt.t = + fun ctxt judgement -> Lwt.return @@ return_no_lwt ctxt judgement + in + let typed_no_lwt ctxt loc instr aft = + log_stack ctxt loc stack_ty aft + >>? fun () -> return_no_lwt ctxt (Typed {loc; instr; bef = stack_ty; aft}) + in + let typed ctxt loc instr aft = + Lwt.return @@ typed_no_lwt ctxt loc instr aft + in + Gas.consume ctxt Typecheck_costs.parse_instr_cycle + >>?= fun ctxt -> + let non_terminal_recursion ?type_logger tc_context ctxt ~legacy script_instr + stack_ty = + if Compare.Int.(stack_depth > 10000) then + fail Typechecking_too_many_recursive_calls + else + parse_instr + ?type_logger + tc_context + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + script_instr + stack_ty + in + match (script_instr, stack_ty) with + (* stack ops *) + | (Prim (loc, I_DROP, [], annot), Item_t (_, rest, _)) -> + ( error_unexpected_annot loc annot >>?= fun () -> typed ctxt loc Drop rest + : (bef judgement * context) tzresult Lwt.t ) + | (Prim (loc, I_DROP, [n], result_annot), whole_stack) -> + parse_uint10 n + >>?= fun whole_n -> + Gas.consume ctxt (Typecheck_costs.proof_argument whole_n) + >>?= fun ctxt -> + let rec make_proof_argument : + type tstk. int -> tstk stack_ty -> tstk dropn_proof_argument tzresult + = + fun n stk -> + match (Compare.Int.(n = 0), stk) with + | (true, rest) -> + ok @@ Dropn_proof_argument (Rest, rest, rest) + | (false, Item_t (v, rest, annot)) -> + make_proof_argument (n - 1) rest + >|? fun (Dropn_proof_argument (n', stack_after_drops, aft')) -> + Dropn_proof_argument + (Prefix n', stack_after_drops, Item_t (v, aft', annot)) + | (_, _) -> + serialize_stack_for_error ctxt whole_stack + >>? fun (whole_stack, _ctxt) -> + error (Bad_stack (loc, I_DROP, whole_n, whole_stack)) + in + error_unexpected_annot loc result_annot + >>?= fun () -> + make_proof_argument whole_n whole_stack + >>?= fun (Dropn_proof_argument (n', stack_after_drops, _aft)) -> + typed ctxt loc (Dropn (whole_n, n')) stack_after_drops + | (Prim (loc, I_DROP, (_ :: _ :: _ as l), _), _) -> + (* Technically, the arities 0 and 1 are allowed but the error only mentions 1. + However, DROP is equivalent to DROP 1 so hinting at an arity of 1 makes sense. *) + fail (Invalid_arity (loc, I_DROP, 1, List.length l)) + | (Prim (loc, I_DUP, [], annot), Item_t (v, rest, stack_annot)) -> + parse_var_annot loc annot ~default:stack_annot + >>?= fun annot -> + record_trace_eval + (fun () -> + serialize_ty_for_error ctxt v + >|? fun (t, _ctxt) -> Non_dupable_type (loc, t)) + (check_dupable_ty ctxt loc v) + >>?= fun ctxt -> + typed ctxt loc Dup (Item_t (v, Item_t (v, rest, stack_annot), annot)) + | (Prim (loc, I_DUP, [n], v_annot), stack_ty) -> + parse_var_annot loc v_annot + >>?= fun annot -> + let rec make_proof_argument : + type before. + int -> before stack_ty -> before dup_n_proof_argument tzresult = + fun n (stack_ty : before stack_ty) -> + match (n, stack_ty) with + | (1, Item_t (hd_ty, _, _)) -> + ok @@ Dup_n_proof_argument (Dup_n_zero, hd_ty) + | (n, Item_t (_, tl_ty, _)) -> + make_proof_argument (n - 1) tl_ty + >|? fun (Dup_n_proof_argument (dup_n_witness, b_ty)) -> + Dup_n_proof_argument (Dup_n_succ dup_n_witness, b_ty) + | _ -> + serialize_stack_for_error ctxt stack_ty + >>? fun (whole_stack, _ctxt) -> + error (Bad_stack (loc, I_DUP, 1, whole_stack)) + in + parse_uint10 n + >>?= fun n -> + Gas.consume ctxt (Typecheck_costs.proof_argument n) + >>?= fun ctxt -> + error_unless (Compare.Int.( > ) n 0) (Dup_n_bad_argument loc) + >>?= fun () -> + record_trace (Dup_n_bad_stack loc) (make_proof_argument n stack_ty) + >>?= fun (Dup_n_proof_argument (witness, after_ty)) -> + record_trace_eval + (fun () -> + serialize_ty_for_error ctxt after_ty + >|? fun (t, _ctxt) -> Non_dupable_type (loc, t)) + (check_dupable_ty ctxt loc after_ty) + >>?= fun ctxt -> + typed ctxt loc (Dup_n (n, witness)) (Item_t (after_ty, stack_ty, annot)) + | (Prim (loc, I_DIG, [n], result_annot), stack) -> + let rec make_proof_argument : + type tstk. int -> tstk stack_ty -> tstk dig_proof_argument tzresult = + fun n stk -> + match (Compare.Int.(n = 0), stk) with + | (true, Item_t (v, rest, annot)) -> + ok @@ Dig_proof_argument (Rest, (v, annot), rest) + | (false, Item_t (v, rest, annot)) -> + make_proof_argument (n - 1) rest + >|? fun (Dig_proof_argument (n', (x, xv), aft')) -> + Dig_proof_argument (Prefix n', (x, xv), Item_t (v, aft', annot)) + | (_, _) -> + serialize_stack_for_error ctxt stack + >>? fun (whole_stack, _ctxt) -> + error (Bad_stack (loc, I_DIG, 1, whole_stack)) + in + parse_uint10 n + >>?= fun n -> + Gas.consume ctxt (Typecheck_costs.proof_argument n) + >>?= fun ctxt -> + error_unexpected_annot loc result_annot + >>?= fun () -> + make_proof_argument n stack + >>?= fun (Dig_proof_argument (n', (x, stack_annot), aft)) -> + typed ctxt loc (Dig (n, n')) (Item_t (x, aft, stack_annot)) + | (Prim (loc, I_DIG, (([] | _ :: _ :: _) as l), _), _) -> + fail (Invalid_arity (loc, I_DIG, 1, List.length l)) + | (Prim (loc, I_DUG, [n], result_annot), Item_t (x, whole_stack, stack_annot)) + -> + parse_uint10 n + >>?= fun whole_n -> + Gas.consume ctxt (Typecheck_costs.proof_argument whole_n) + >>?= fun ctxt -> + let rec make_proof_argument : + type tstk x. + int -> + x ty -> + var_annot option -> + tstk stack_ty -> + (tstk, x) dug_proof_argument tzresult = + fun n x stack_annot stk -> + match (Compare.Int.(n = 0), stk) with + | (true, rest) -> + ok @@ Dug_proof_argument (Rest, (), Item_t (x, rest, stack_annot)) + | (false, Item_t (v, rest, annot)) -> + make_proof_argument (n - 1) x stack_annot rest + >|? fun (Dug_proof_argument (n', (), aft')) -> + Dug_proof_argument (Prefix n', (), Item_t (v, aft', annot)) + | (_, _) -> + serialize_stack_for_error ctxt whole_stack + >>? fun (whole_stack, _ctxt) -> + error (Bad_stack (loc, I_DUG, whole_n, whole_stack)) + in + error_unexpected_annot loc result_annot + >>?= fun () -> + make_proof_argument whole_n x stack_annot whole_stack + >>?= fun (Dug_proof_argument (n', (), aft)) -> + typed ctxt loc (Dug (whole_n, n')) aft + | (Prim (loc, I_DUG, [_], result_annot), (Empty_t as stack)) -> + Lwt.return + ( error_unexpected_annot loc result_annot + >>? fun () -> + serialize_stack_for_error ctxt stack + >>? fun (stack, _ctxt) -> error (Bad_stack (loc, I_DUG, 1, stack)) ) + | (Prim (loc, I_DUG, (([] | _ :: _ :: _) as l), _), _) -> + fail (Invalid_arity (loc, I_DUG, 1, List.length l)) + | ( Prim (loc, I_SWAP, [], annot), + Item_t (v, Item_t (w, rest, stack_annot), cur_top_annot) ) -> + error_unexpected_annot loc annot + >>?= fun () -> + typed + ctxt + loc + Swap + (Item_t (w, Item_t (v, rest, cur_top_annot), stack_annot)) + | (Prim (loc, I_PUSH, [t; d], annot), stack) -> + parse_var_annot loc annot + >>?= fun annot -> + parse_packable_ty ctxt ~legacy t + >>?= fun (Ex_ty t, ctxt) -> + parse_data + ?type_logger + ~stack_depth:(stack_depth + 1) + ctxt + ~legacy + ~allow_forged:false + t + d + >>=? fun (v, ctxt) -> typed ctxt loc (Const v) (Item_t (t, stack, annot)) + | (Prim (loc, I_UNIT, [], annot), stack) -> + parse_var_type_annot loc annot + >>?= fun (annot, ty_name) -> + typed ctxt loc (Const ()) (Item_t (Unit_t ty_name, stack, annot)) + (* options *) + | (Prim (loc, I_SOME, [], annot), Item_t (t, rest, _)) -> + parse_var_type_annot loc annot + >>?= fun (annot, ty_name) -> + typed ctxt loc Cons_some (Item_t (Option_t (t, ty_name), rest, annot)) + | (Prim (loc, I_NONE, [t], annot), stack) -> + parse_any_ty ctxt ~legacy t + >>?= fun (Ex_ty t, ctxt) -> + parse_var_type_annot loc annot + >>?= fun (annot, ty_name) -> + typed + ctxt + loc + (Cons_none t) + (Item_t (Option_t (t, ty_name), stack, annot)) + | ( Prim (loc, I_IF_NONE, [bt; bf], annot), + (Item_t (Option_t (t, _), rest, option_annot) as bef) ) -> + check_kind [Seq_kind] bt + >>?= fun () -> + check_kind [Seq_kind] bf + >>?= fun () -> + error_unexpected_annot loc annot + >>?= fun () -> + let annot = gen_access_annot option_annot default_some_annot in + non_terminal_recursion ?type_logger tc_context ctxt ~legacy bt rest + >>=? fun (btr, ctxt) -> + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + bf + (Item_t (t, rest, annot)) + >>=? fun (bfr, ctxt) -> + let branch ibt ibf = + {loc; instr = If_none (ibt, ibf); bef; aft = ibt.aft} + in + merge_branches ~legacy ctxt loc btr bfr {branch} + >>?= fun (judgement, ctxt) -> return ctxt judgement + (* pairs *) + | ( Prim (loc, I_PAIR, [], annot), + Item_t (a, Item_t (b, rest, snd_annot), fst_annot) ) -> + parse_constr_annot + loc + annot + ~if_special_first:(var_to_field_annot fst_annot) + ~if_special_second:(var_to_field_annot snd_annot) + >>?= fun (annot, ty_name, l_field, r_field) -> + typed + ctxt + loc + Cons_pair + (Item_t + ( Pair_t ((a, l_field, fst_annot), (b, r_field, snd_annot), ty_name), + rest, + annot )) + | (Prim (loc, I_PAIR, [n], annot), stack_ty) -> + parse_var_annot loc annot + >>?= fun annot -> + let rec make_proof_argument : + type before. + int -> + before stack_ty -> + (before comb_proof_argument * var_annot option) tzresult = + fun n stack_ty -> + match (n, stack_ty) with + | (1, Item_t (a_ty, tl_ty, a_annot_opt)) -> + ok + ( Comb_proof_argument (Comb_one, Item_t (a_ty, tl_ty, annot)), + a_annot_opt ) + | (n, Item_t (a_ty, tl_ty, prop_annot_opt)) -> + make_proof_argument (n - 1) tl_ty + >|? fun ( Comb_proof_argument + (comb_witness, Item_t (b_ty, tl_ty', annot)), + b_annot_opt ) -> + let prop_annot_opt' = var_to_field_annot prop_annot_opt in + let b_prop_annot_opt = var_to_field_annot b_annot_opt in + let pair_t = + Pair_t + ( (a_ty, prop_annot_opt', None), + (b_ty, b_prop_annot_opt, None), + None ) + in + ( Comb_proof_argument + (Comb_succ comb_witness, Item_t (pair_t, tl_ty', annot)), + None ) + | _ -> + serialize_stack_for_error ctxt stack_ty + >>? fun (whole_stack, _ctxt) -> + error (Bad_stack (loc, I_PAIR, 1, whole_stack)) + in + parse_uint10 n + >>?= fun n -> + Gas.consume ctxt (Typecheck_costs.proof_argument n) + >>?= fun ctxt -> + error_unless (Compare.Int.( > ) n 1) (Pair_bad_argument loc) + >>?= fun () -> + make_proof_argument n stack_ty + >>?= fun (Comb_proof_argument (witness, after_ty), _none) -> + typed ctxt loc (Comb (n, witness)) after_ty + | (Prim (loc, I_UNPAIR, [n], annot), stack_ty) -> + error_unexpected_annot loc annot + >>?= fun () -> + let rec make_proof_argument : + type before. + int -> before stack_ty -> before uncomb_proof_argument tzresult = + fun n stack_ty -> + match (n, stack_ty) with + | (1, Item_t (a_ty, tl_ty, annot)) -> + ok + @@ Uncomb_proof_argument (Uncomb_one, Item_t (a_ty, tl_ty, annot)) + | ( n, + Item_t + ( Pair_t ((a_ty, field_opt, _), (b_ty, b_field_opt, _), _), + tl_ty, + _ ) ) -> + let b_annot = Script_ir_annot.field_to_var_annot b_field_opt in + make_proof_argument (n - 1) (Item_t (b_ty, tl_ty, b_annot)) + >|? fun (Uncomb_proof_argument (uncomb_witness, after_ty)) -> + Uncomb_proof_argument + ( Uncomb_succ uncomb_witness, + Item_t + (a_ty, after_ty, Script_ir_annot.field_to_var_annot field_opt) + ) + | _ -> + serialize_stack_for_error ctxt stack_ty + >>? fun (whole_stack, _ctxt) -> + error (Bad_stack (loc, I_UNPAIR, 1, whole_stack)) + in + parse_uint10 n + >>?= fun n -> + Gas.consume ctxt (Typecheck_costs.proof_argument n) + >>?= fun ctxt -> + error_unless (Compare.Int.( > ) n 1) (Unpair_bad_argument loc) + >>?= fun () -> + make_proof_argument n stack_ty + >>?= fun (Uncomb_proof_argument (witness, after_ty)) -> + typed ctxt loc (Uncomb (n, witness)) after_ty + | (Prim (loc, I_GET, [n], annot), Item_t (comb_ty, rest_ty, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + let rec make_proof_argument : + type before. + int -> before ty -> before comb_get_proof_argument tzresult = + fun n ty -> + match (n, ty) with + | (0, value_ty) -> + ok @@ Comb_get_proof_argument (Comb_get_zero, value_ty) + | (1, Pair_t ((hd_ty, _at1, _at2), _, _annot)) -> + ok @@ Comb_get_proof_argument (Comb_get_one, hd_ty) + | (n, Pair_t (_, (tl_ty, _bt1, _bt2), _annot)) -> + make_proof_argument (n - 2) tl_ty + >|? fun (Comb_get_proof_argument (comb_get_left_witness, ty')) -> + Comb_get_proof_argument + (Comb_get_plus_two comb_get_left_witness, ty') + | _ -> + serialize_stack_for_error ctxt stack_ty + >>? fun (whole_stack, _ctxt) -> + error (Bad_stack (loc, I_GET, 1, whole_stack)) + in + parse_uint11 n + >>?= fun n -> + Gas.consume ctxt (Typecheck_costs.proof_argument n) + >>?= fun ctxt -> + make_proof_argument n comb_ty + >>?= fun (Comb_get_proof_argument (witness, ty')) -> + let after_stack_ty = Item_t (ty', rest_ty, annot) in + typed ctxt loc (Comb_get (n, witness)) after_stack_ty + | ( Prim (loc, I_UPDATE, [n], annot), + Item_t (value_ty, Item_t (comb_ty, rest_ty, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + let rec make_proof_argument : + type value before. + int -> + value ty -> + before ty -> + (value, before) comb_set_proof_argument tzresult = + fun n value_ty ty -> + match (n, ty) with + | (0, _) -> + ok @@ Comb_set_proof_argument (Comb_set_zero, value_ty) + | (1, Pair_t ((_hd_ty, at1, at2), (tl_ty, bt1, bt2), annot)) -> + let after_ty = + Pair_t ((value_ty, at1, at2), (tl_ty, bt1, bt2), annot) + in + ok @@ Comb_set_proof_argument (Comb_set_one, after_ty) + | (n, Pair_t ((hd_ty, at1, at2), (tl_ty, bt1, bt2), annot)) -> + make_proof_argument (n - 2) value_ty tl_ty + >|? fun (Comb_set_proof_argument (comb_set_left_witness, tl_ty')) -> + let after_ty = + Pair_t ((hd_ty, at1, at2), (tl_ty', bt1, bt2), annot) + in + Comb_set_proof_argument + (Comb_set_plus_two comb_set_left_witness, after_ty) + | _ -> + serialize_stack_for_error ctxt stack_ty + >>? fun (whole_stack, _ctxt) -> + error (Bad_stack (loc, I_UPDATE, 2, whole_stack)) + in + parse_uint11 n + >>?= fun n -> + Gas.consume ctxt (Typecheck_costs.proof_argument n) + >>?= fun ctxt -> + make_proof_argument n value_ty comb_ty + >>?= fun (Comb_set_proof_argument (witness, after_ty)) -> + let after_stack_ty = Item_t (after_ty, rest_ty, annot) in + typed ctxt loc (Comb_set (n, witness)) after_stack_ty + | ( Prim (loc, I_UNPAIR, [], annot), + Item_t + ( Pair_t + ( (a, expected_field_annot_a, a_annot), + (b, expected_field_annot_b, b_annot), + _ ), + rest, + pair_annot ) ) -> + parse_unpair_annot + loc + annot + ~pair_annot + ~value_annot_car:a_annot + ~value_annot_cdr:b_annot + ~field_name_car:expected_field_annot_a + ~field_name_cdr:expected_field_annot_b + >>?= fun (annot_a, annot_b, field_a, field_b) -> + check_correct_field field_a expected_field_annot_a + >>?= fun () -> + check_correct_field field_b expected_field_annot_b + >>?= fun () -> + typed ctxt loc Unpair (Item_t (a, Item_t (b, rest, annot_b), annot_a)) + | ( Prim (loc, I_CAR, [], annot), + Item_t + (Pair_t ((a, expected_field_annot, a_annot), _, _), rest, pair_annot) + ) -> + parse_destr_annot + loc + annot + ~pair_annot + ~value_annot:a_annot + ~field_name:expected_field_annot + ~default_accessor:default_car_annot + >>?= fun (annot, field_annot) -> + check_correct_field field_annot expected_field_annot + >>?= fun () -> typed ctxt loc Car (Item_t (a, rest, annot)) + | ( Prim (loc, I_CDR, [], annot), + Item_t + (Pair_t (_, (b, expected_field_annot, b_annot), _), rest, pair_annot) + ) -> + parse_destr_annot + loc + annot + ~pair_annot + ~value_annot:b_annot + ~field_name:expected_field_annot + ~default_accessor:default_cdr_annot + >>?= fun (annot, field_annot) -> + check_correct_field field_annot expected_field_annot + >>?= fun () -> typed ctxt loc Cdr (Item_t (b, rest, annot)) + (* unions *) + | (Prim (loc, I_LEFT, [tr], annot), Item_t (tl, rest, stack_annot)) -> + parse_any_ty ctxt ~legacy tr + >>?= fun (Ex_ty tr, ctxt) -> + parse_constr_annot + loc + annot + ~if_special_first:(var_to_field_annot stack_annot) + >>?= fun (annot, tname, l_field, r_field) -> + typed + ctxt + loc + Cons_left + (Item_t (Union_t ((tl, l_field), (tr, r_field), tname), rest, annot)) + | (Prim (loc, I_RIGHT, [tl], annot), Item_t (tr, rest, stack_annot)) -> + parse_any_ty ctxt ~legacy tl + >>?= fun (Ex_ty tl, ctxt) -> + parse_constr_annot + loc + annot + ~if_special_second:(var_to_field_annot stack_annot) + >>?= fun (annot, tname, l_field, r_field) -> + typed + ctxt + loc + Cons_right + (Item_t (Union_t ((tl, l_field), (tr, r_field), tname), rest, annot)) + | ( Prim (loc, I_IF_LEFT, [bt; bf], annot), + ( Item_t (Union_t ((tl, l_field), (tr, r_field), _), rest, union_annot) + as bef ) ) -> + check_kind [Seq_kind] bt + >>?= fun () -> + check_kind [Seq_kind] bf + >>?= fun () -> + error_unexpected_annot loc annot + >>?= fun () -> + let left_annot = + gen_access_annot union_annot l_field ~default:default_left_annot + in + let right_annot = + gen_access_annot union_annot r_field ~default:default_right_annot + in + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + bt + (Item_t (tl, rest, left_annot)) + >>=? fun (btr, ctxt) -> + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + bf + (Item_t (tr, rest, right_annot)) + >>=? fun (bfr, ctxt) -> + let branch ibt ibf = + {loc; instr = If_left (ibt, ibf); bef; aft = ibt.aft} + in + merge_branches ~legacy ctxt loc btr bfr {branch} + >>?= fun (judgement, ctxt) -> return ctxt judgement + (* lists *) + | (Prim (loc, I_NIL, [t], annot), stack) -> + parse_any_ty ctxt ~legacy t + >>?= fun (Ex_ty t, ctxt) -> + parse_var_type_annot loc annot + >>?= fun (annot, ty_name) -> + typed ctxt loc Nil (Item_t (List_t (t, ty_name), stack, annot)) + | ( Prim (loc, I_CONS, [], annot), + Item_t (tv, Item_t (List_t (t, ty_name), rest, _), _) ) -> + check_item_ty ctxt tv t loc I_CONS 1 2 + >>?= fun (Eq, t, ctxt) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Cons_list (Item_t (List_t (t, ty_name), rest, annot)) + | ( Prim (loc, I_IF_CONS, [bt; bf], annot), + (Item_t (List_t (t, ty_name), rest, list_annot) as bef) ) -> + check_kind [Seq_kind] bt + >>?= fun () -> + check_kind [Seq_kind] bf + >>?= fun () -> + error_unexpected_annot loc annot + >>?= fun () -> + let hd_annot = gen_access_annot list_annot default_hd_annot in + let tl_annot = gen_access_annot list_annot default_tl_annot in + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + bt + (Item_t (t, Item_t (List_t (t, ty_name), rest, tl_annot), hd_annot)) + >>=? fun (btr, ctxt) -> + non_terminal_recursion ?type_logger tc_context ctxt ~legacy bf rest + >>=? fun (bfr, ctxt) -> + let branch ibt ibf = + {loc; instr = If_cons (ibt, ibf); bef; aft = ibt.aft} + in + merge_branches ~legacy ctxt loc btr bfr {branch} + >>?= fun (judgement, ctxt) -> return ctxt judgement + | (Prim (loc, I_SIZE, [], annot), Item_t (List_t _, rest, _)) -> + parse_var_type_annot loc annot + >>?= fun (annot, tname) -> + typed ctxt loc List_size (Item_t (Nat_t tname, rest, annot)) + | ( Prim (loc, I_MAP, [body], annot), + Item_t (List_t (elt, _), starting_rest, list_annot) ) -> ( + check_kind [Seq_kind] body + >>?= fun () -> + parse_var_type_annot loc annot + >>?= fun (ret_annot, list_ty_name) -> + let elt_annot = gen_access_annot list_annot default_elt_annot in + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + body + (Item_t (elt, starting_rest, elt_annot)) + >>=? fun (judgement, ctxt) -> + match judgement with + | Typed ({aft = Item_t (ret, rest, _); _} as ibody) -> + let invalid_map_body () = + serialize_stack_for_error ctxt ibody.aft + >|? fun (aft, _ctxt) -> Invalid_map_body (loc, aft) + in + Lwt.return + @@ record_trace_eval + invalid_map_body + ( merge_stacks ~legacy loc ctxt 1 rest starting_rest + >>? fun (Eq, rest, ctxt) -> + typed_no_lwt + ctxt + loc + (List_map ibody) + (Item_t (List_t (ret, list_ty_name), rest, ret_annot)) ) + | Typed {aft; _} -> + Lwt.return + ( serialize_stack_for_error ctxt aft + >>? fun (aft, _ctxt) -> error (Invalid_map_body (loc, aft)) ) + | Failed _ -> + fail (Invalid_map_block_fail loc) ) + | ( Prim (loc, I_ITER, [body], annot), + Item_t (List_t (elt, _), rest, list_annot) ) -> ( + check_kind [Seq_kind] body + >>?= fun () -> + error_unexpected_annot loc annot + >>?= fun () -> + let elt_annot = gen_access_annot list_annot default_elt_annot in + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + body + (Item_t (elt, rest, elt_annot)) + >>=? fun (judgement, ctxt) -> + match judgement with + | Typed ({aft; _} as ibody) -> + let invalid_iter_body () = + serialize_stack_for_error ctxt ibody.aft + >>? fun (aft, ctxt) -> + serialize_stack_for_error ctxt rest + >|? fun (rest, _ctxt) -> Invalid_iter_body (loc, rest, aft) + in + Lwt.return + @@ record_trace_eval + invalid_iter_body + ( merge_stacks ~legacy loc ctxt 1 aft rest + >>? fun (Eq, rest, ctxt) -> + typed_no_lwt ctxt loc (List_iter ibody) rest ) + | Failed {descr} -> + typed ctxt loc (List_iter (descr rest)) rest ) + (* sets *) + | (Prim (loc, I_EMPTY_SET, [t], annot), rest) -> + parse_comparable_ty ctxt t + >>?= fun (Ex_comparable_ty t, ctxt) -> + parse_var_type_annot loc annot + >>?= fun (annot, tname) -> + typed ctxt loc (Empty_set t) (Item_t (Set_t (t, tname), rest, annot)) + | ( Prim (loc, I_ITER, [body], annot), + Item_t (Set_t (comp_elt, _), rest, set_annot) ) -> ( + check_kind [Seq_kind] body + >>?= fun () -> + error_unexpected_annot loc annot + >>?= fun () -> + let elt_annot = gen_access_annot set_annot default_elt_annot in + let elt = ty_of_comparable_ty comp_elt in + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + body + (Item_t (elt, rest, elt_annot)) + >>=? fun (judgement, ctxt) -> + match judgement with + | Typed ({aft; _} as ibody) -> + let invalid_iter_body () = + serialize_stack_for_error ctxt ibody.aft + >>? fun (aft, ctxt) -> + serialize_stack_for_error ctxt rest + >|? fun (rest, _ctxt) -> Invalid_iter_body (loc, rest, aft) + in + Lwt.return + @@ record_trace_eval + invalid_iter_body + ( merge_stacks ~legacy loc ctxt 1 aft rest + >>? fun (Eq, rest, ctxt) -> + typed_no_lwt ctxt loc (Set_iter ibody) rest ) + | Failed {descr} -> + typed ctxt loc (Set_iter (descr rest)) rest ) + | ( Prim (loc, I_MEM, [], annot), + Item_t (v, Item_t (Set_t (elt, _), rest, _), _) ) -> + let elt = ty_of_comparable_ty elt in + parse_var_type_annot loc annot + >>?= fun (annot, tname) -> + check_item_ty ctxt elt v loc I_MEM 1 2 + >>?= fun (Eq, _, ctxt) -> + typed ctxt loc Set_mem (Item_t (Bool_t tname, rest, annot)) + | ( Prim (loc, I_UPDATE, [], annot), + Item_t + ( v, + Item_t (Bool_t _, Item_t (Set_t (elt, tname), rest, set_annot), _), + _ ) ) -> + check_item_ty ctxt (ty_of_comparable_ty elt) v loc I_UPDATE 1 3 + >>?= fun (Eq, _, ctxt) -> + parse_var_annot loc annot ~default:set_annot + >>?= fun annot -> + typed ctxt loc Set_update (Item_t (Set_t (elt, tname), rest, annot)) + | (Prim (loc, I_SIZE, [], annot), Item_t (Set_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Set_size (Item_t (Nat_t None, rest, annot)) + (* maps *) + | (Prim (loc, I_EMPTY_MAP, [tk; tv], annot), stack) -> + parse_comparable_ty ctxt tk + >>?= fun (Ex_comparable_ty tk, ctxt) -> + parse_any_ty ctxt ~legacy tv + >>?= fun (Ex_ty tv, ctxt) -> + parse_var_type_annot loc annot + >>?= fun (annot, ty_name) -> + typed + ctxt + loc + (Empty_map (tk, tv)) + (Item_t (Map_t (tk, tv, ty_name), stack, annot)) + | ( Prim (loc, I_MAP, [body], annot), + Item_t (Map_t (ck, elt, _), starting_rest, _map_annot) ) -> ( + let k = ty_of_comparable_ty ck in + check_kind [Seq_kind] body + >>?= fun () -> + parse_var_type_annot loc annot + >>?= fun (ret_annot, ty_name) -> + let k_name = field_to_var_annot default_key_annot in + let e_name = field_to_var_annot default_elt_annot in + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + body + (Item_t + ( Pair_t ((k, None, k_name), (elt, None, e_name), None), + starting_rest, + None )) + >>=? fun (judgement, ctxt) -> + match judgement with + | Typed ({aft = Item_t (ret, rest, _); _} as ibody) -> + let invalid_map_body () = + serialize_stack_for_error ctxt ibody.aft + >|? fun (aft, _ctxt) -> Invalid_map_body (loc, aft) + in + Lwt.return + @@ record_trace_eval + invalid_map_body + ( merge_stacks ~legacy loc ctxt 1 rest starting_rest + >>? fun (Eq, rest, ctxt) -> + typed_no_lwt + ctxt + loc + (Map_map ibody) + (Item_t (Map_t (ck, ret, ty_name), rest, ret_annot)) ) + | Typed {aft; _} -> + Lwt.return + ( serialize_stack_for_error ctxt aft + >>? fun (aft, _ctxt) -> error (Invalid_map_body (loc, aft)) ) + | Failed _ -> + fail (Invalid_map_block_fail loc) ) + | ( Prim (loc, I_ITER, [body], annot), + Item_t (Map_t (comp_elt, element_ty, _), rest, _map_annot) ) -> ( + check_kind [Seq_kind] body + >>?= fun () -> + error_unexpected_annot loc annot + >>?= fun () -> + let k_name = field_to_var_annot default_key_annot in + let e_name = field_to_var_annot default_elt_annot in + let key = ty_of_comparable_ty comp_elt in + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + body + (Item_t + ( Pair_t ((key, None, k_name), (element_ty, None, e_name), None), + rest, + None )) + >>=? fun (judgement, ctxt) -> + match judgement with + | Typed ({aft; _} as ibody) -> + let invalid_iter_body () = + serialize_stack_for_error ctxt ibody.aft + >>? fun (aft, ctxt) -> + serialize_stack_for_error ctxt rest + >|? fun (rest, _ctxt) -> Invalid_iter_body (loc, rest, aft) + in + Lwt.return + @@ record_trace_eval + invalid_iter_body + ( merge_stacks ~legacy loc ctxt 1 aft rest + >>? fun (Eq, rest, ctxt) -> + typed_no_lwt ctxt loc (Map_iter ibody) rest ) + | Failed {descr} -> + typed ctxt loc (Map_iter (descr rest)) rest ) + | ( Prim (loc, I_MEM, [], annot), + Item_t (vk, Item_t (Map_t (ck, _, _), rest, _), _) ) -> + let k = ty_of_comparable_ty ck in + check_item_ty ctxt vk k loc I_MEM 1 2 + >>?= fun (Eq, _, ctxt) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Map_mem (Item_t (Bool_t None, rest, annot)) + | ( Prim (loc, I_GET, [], annot), + Item_t (vk, Item_t (Map_t (ck, elt, _), rest, _), _) ) -> + let k = ty_of_comparable_ty ck in + check_item_ty ctxt vk k loc I_GET 1 2 + >>?= fun (Eq, _, ctxt) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Map_get (Item_t (Option_t (elt, None), rest, annot)) + | ( Prim (loc, I_UPDATE, [], annot), + Item_t + ( vk, + Item_t + ( Option_t (vv, _), + Item_t (Map_t (ck, v, map_name), rest, map_annot), + _ ), + _ ) ) -> + let k = ty_of_comparable_ty ck in + check_item_ty ctxt vk k loc I_UPDATE 1 3 + >>?= fun (Eq, _, ctxt) -> + check_item_ty ctxt vv v loc I_UPDATE 2 3 + >>?= fun (Eq, v, ctxt) -> + parse_var_annot loc annot ~default:map_annot + >>?= fun annot -> + typed ctxt loc Map_update (Item_t (Map_t (ck, v, map_name), rest, annot)) + | ( Prim (loc, I_GET_AND_UPDATE, [], annot), + Item_t + ( vk, + Item_t + ( Option_t (vv, vname), + Item_t (Map_t (ck, v, map_name), rest, map_annot), + v_annot ), + _ ) ) -> + let k = ty_of_comparable_ty ck in + check_item_ty ctxt vk k loc I_GET_AND_UPDATE 1 3 + >>?= fun (Eq, _, ctxt) -> + check_item_ty ctxt vv v loc I_GET_AND_UPDATE 2 3 + >>?= fun (Eq, v, ctxt) -> + parse_var_annot loc annot ~default:map_annot + >>?= fun annot -> + typed + ctxt + loc + Map_get_and_update + (Item_t + ( Option_t (vv, vname), + Item_t (Map_t (ck, v, map_name), rest, annot), + v_annot )) + | (Prim (loc, I_SIZE, [], annot), Item_t (Map_t (_, _, _), rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Map_size (Item_t (Nat_t None, rest, annot)) + (* big_map *) + | (Prim (loc, I_EMPTY_BIG_MAP, [tk; tv], annot), stack) -> + parse_comparable_ty ctxt tk + >>?= fun (Ex_comparable_ty tk, ctxt) -> + parse_big_map_value_ty ctxt ~legacy tv + >>?= fun (Ex_ty tv, ctxt) -> + parse_var_type_annot loc annot + >>?= fun (annot, ty_name) -> + typed + ctxt + loc + (Empty_big_map (tk, tv)) + (Item_t (Big_map_t (tk, tv, ty_name), stack, annot)) + | ( Prim (loc, I_MEM, [], annot), + Item_t (set_key, Item_t (Big_map_t (map_key, _, _), rest, _), _) ) -> + let k = ty_of_comparable_ty map_key in + check_item_ty ctxt set_key k loc I_MEM 1 2 + >>?= fun (Eq, _, ctxt) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Big_map_mem (Item_t (Bool_t None, rest, annot)) + | ( Prim (loc, I_GET, [], annot), + Item_t (vk, Item_t (Big_map_t (ck, elt, _), rest, _), _) ) -> + let k = ty_of_comparable_ty ck in + check_item_ty ctxt vk k loc I_GET 1 2 + >>?= fun (Eq, _, ctxt) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Big_map_get (Item_t (Option_t (elt, None), rest, annot)) + | ( Prim (loc, I_UPDATE, [], annot), + Item_t + ( set_key, + Item_t + ( Option_t (set_value, _), + Item_t (Big_map_t (map_key, map_value, map_name), rest, map_annot), + _ ), + _ ) ) -> + let k = ty_of_comparable_ty map_key in + check_item_ty ctxt set_key k loc I_UPDATE 1 3 + >>?= fun (Eq, _, ctxt) -> + check_item_ty ctxt set_value map_value loc I_UPDATE 2 3 + >>?= fun (Eq, map_value, ctxt) -> + parse_var_annot loc annot ~default:map_annot + >>?= fun annot -> + typed + ctxt + loc + Big_map_update + (Item_t (Big_map_t (map_key, map_value, map_name), rest, annot)) + | ( Prim (loc, I_GET_AND_UPDATE, [], annot), + Item_t + ( vk, + Item_t + ( Option_t (vv, vname), + Item_t (Big_map_t (ck, v, map_name), rest, map_annot), + v_annot ), + _ ) ) -> + let k = ty_of_comparable_ty ck in + check_item_ty ctxt vk k loc I_GET_AND_UPDATE 1 3 + >>?= fun (Eq, _, ctxt) -> + check_item_ty ctxt vv v loc I_GET_AND_UPDATE 2 3 + >>?= fun (Eq, v, ctxt) -> + parse_var_annot loc annot ~default:map_annot + >>?= fun annot -> + typed + ctxt + loc + Big_map_get_and_update + (Item_t + ( Option_t (vv, vname), + Item_t (Big_map_t (ck, v, map_name), rest, annot), + v_annot )) + (* Sapling *) + | (Prim (loc, I_SAPLING_EMPTY_STATE, [memo_size], annot), rest) -> + parse_memo_size memo_size + >>?= fun memo_size -> + parse_var_annot loc annot ~default:default_sapling_state_annot + >>?= fun annot -> + typed + ctxt + loc + (Sapling_empty_state {memo_size}) + (Item_t (Sapling_state_t (memo_size, None), rest, annot)) + | ( Prim (loc, I_SAPLING_VERIFY_UPDATE, [], _), + Item_t + ( Sapling_transaction_t (transaction_memo_size, _), + Item_t + ( (Sapling_state_t (state_memo_size, _) as state_ty), + rest, + stack_annot ), + _ ) ) -> + merge_memo_sizes state_memo_size transaction_memo_size + >>?= fun _memo_size -> + typed + ctxt + loc + Sapling_verify_update + (Item_t + ( Option_t + ( Pair_t + ( (Int_t None, None, default_sapling_balance_annot), + (state_ty, None, None), + None ), + None ), + rest, + stack_annot )) + (* control *) + | (Seq (loc, []), stack) -> + typed ctxt loc Nop stack + | (Seq (loc, [single]), stack) -> ( + non_terminal_recursion ?type_logger tc_context ctxt ~legacy single stack + >>=? fun (judgement, ctxt) -> + match judgement with + | Typed ({aft; _} as instr) -> + let nop = {bef = aft; loc; aft; instr = Nop} in + typed ctxt loc (Seq (instr, nop)) aft + | Failed {descr; _} -> + let descr aft = + let nop = {bef = aft; loc; aft; instr = Nop} in + let descr = descr aft in + {descr with instr = Seq (descr, nop)} + in + return ctxt (Failed {descr}) ) + | (Seq (loc, hd :: tl), stack) -> ( + non_terminal_recursion ?type_logger tc_context ctxt ~legacy hd stack + >>=? fun (judgement, ctxt) -> + match judgement with + | Failed _ -> + fail (Fail_not_in_tail_position (Micheline.location hd)) + | Typed ({aft = middle; _} as ihd) -> ( + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + (Seq (-1, tl)) + middle + >>=? fun (judgement, ctxt) -> + match judgement with + | Failed {descr} -> + let descr ret = + {loc; instr = Seq (ihd, descr ret); bef = stack; aft = ret} + in + return ctxt (Failed {descr}) + | Typed itl -> + typed ctxt loc (Seq (ihd, itl)) itl.aft ) ) + | (Prim (loc, I_IF, [bt; bf], annot), (Item_t (Bool_t _, rest, _) as bef)) -> + check_kind [Seq_kind] bt + >>?= fun () -> + check_kind [Seq_kind] bf + >>?= fun () -> + error_unexpected_annot loc annot + >>?= fun () -> + non_terminal_recursion ?type_logger tc_context ctxt ~legacy bt rest + >>=? fun (btr, ctxt) -> + non_terminal_recursion ?type_logger tc_context ctxt ~legacy bf rest + >>=? fun (bfr, ctxt) -> + let branch ibt ibf = {loc; instr = If (ibt, ibf); bef; aft = ibt.aft} in + merge_branches ~legacy ctxt loc btr bfr {branch} + >>?= fun (judgement, ctxt) -> return ctxt judgement + | ( Prim (loc, I_LOOP, [body], annot), + (Item_t (Bool_t _, rest, _stack_annot) as stack) ) -> ( + check_kind [Seq_kind] body + >>?= fun () -> + error_unexpected_annot loc annot + >>?= fun () -> + non_terminal_recursion ?type_logger tc_context ctxt ~legacy body rest + >>=? fun (judgement, ctxt) -> + match judgement with + | Typed ibody -> + let unmatched_branches () = + serialize_stack_for_error ctxt ibody.aft + >>? fun (aft, ctxt) -> + serialize_stack_for_error ctxt stack + >|? fun (stack, _ctxt) -> Unmatched_branches (loc, aft, stack) + in + Lwt.return + @@ record_trace_eval + unmatched_branches + ( merge_stacks ~legacy loc ctxt 1 ibody.aft stack + >>? fun (Eq, _stack, ctxt) -> + typed_no_lwt ctxt loc (Loop ibody) rest ) + | Failed {descr} -> + let ibody = descr stack in + typed ctxt loc (Loop ibody) rest ) + | ( Prim (loc, I_LOOP_LEFT, [body], annot), + (Item_t (Union_t ((tl, l_field), (tr, _), _), rest, union_annot) as stack) + ) -> ( + check_kind [Seq_kind] body + >>?= fun () -> + parse_var_annot loc annot + >>?= fun annot -> + let l_annot = + gen_access_annot union_annot l_field ~default:default_left_annot + in + non_terminal_recursion + ?type_logger + tc_context + ctxt + ~legacy + body + (Item_t (tl, rest, l_annot)) + >>=? fun (judgement, ctxt) -> + match judgement with + | Typed ibody -> + let unmatched_branches () = + serialize_stack_for_error ctxt ibody.aft + >>? fun (aft, ctxt) -> + serialize_stack_for_error ctxt stack + >|? fun (stack, _ctxt) -> Unmatched_branches (loc, aft, stack) + in + Lwt.return + @@ record_trace_eval + unmatched_branches + ( merge_stacks ~legacy loc ctxt 1 ibody.aft stack + >>? fun (Eq, _stack, ctxt) -> + typed_no_lwt + ctxt + loc + (Loop_left ibody) + (Item_t (tr, rest, annot)) ) + | Failed {descr} -> + let ibody = descr stack in + typed ctxt loc (Loop_left ibody) (Item_t (tr, rest, annot)) ) + | (Prim (loc, I_LAMBDA, [arg; ret; code], annot), stack) -> + parse_any_ty ctxt ~legacy arg + >>?= fun (Ex_ty arg, ctxt) -> + parse_any_ty ctxt ~legacy ret + >>?= fun (Ex_ty ret, ctxt) -> + check_kind [Seq_kind] code + >>?= fun () -> + parse_var_annot loc annot + >>?= fun annot -> + parse_returning + Lambda + ?type_logger + ~stack_depth + ctxt + ~legacy + (arg, default_arg_annot) + ret + code + >>=? fun (lambda, ctxt) -> + typed + ctxt + loc + (Lambda lambda) + (Item_t (Lambda_t (arg, ret, None), stack, annot)) + | ( Prim (loc, I_EXEC, [], annot), + Item_t (arg, Item_t (Lambda_t (param, ret, _), rest, _), _) ) -> + check_item_ty ctxt arg param loc I_EXEC 1 2 + >>?= fun (Eq, _, ctxt) -> + parse_var_annot loc annot + >>?= fun annot -> typed ctxt loc Exec (Item_t (ret, rest, annot)) + | ( Prim (loc, I_APPLY, [], annot), + Item_t + ( capture, + Item_t + ( Lambda_t + (Pair_t ((capture_ty, _, _), (arg_ty, _, _), lam_annot), ret, _), + rest, + _ ), + _ ) ) -> + check_packable ~legacy:false loc capture_ty + >>?= fun () -> + check_item_ty ctxt capture capture_ty loc I_APPLY 1 2 + >>?= fun (Eq, capture_ty, ctxt) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + (Apply capture_ty) + (Item_t (Lambda_t (arg_ty, ret, lam_annot), rest, annot)) + | (Prim (loc, I_DIP, [code], annot), Item_t (v, rest, stack_annot)) -> ( + error_unexpected_annot loc annot + >>?= fun () -> + check_kind [Seq_kind] code + >>?= fun () -> + non_terminal_recursion + ?type_logger + (add_dip v stack_annot tc_context) + ctxt + ~legacy + code + rest + >>=? fun (judgement, ctxt) -> + match judgement with + | Typed descr -> + typed ctxt loc (Dip descr) (Item_t (v, descr.aft, stack_annot)) + | Failed _ -> + fail (Fail_not_in_tail_position loc) ) + | (Prim (loc, I_DIP, [n; code], result_annot), stack) -> + parse_uint10 n + >>?= fun n -> + Gas.consume ctxt (Typecheck_costs.proof_argument n) + >>?= fun ctxt -> + let rec make_proof_argument : + type tstk. + int + (* -> (fbef stack_ty -> (fbef judgement * context) tzresult Lwt.t) *) -> + tc_context -> + tstk stack_ty -> + tstk dipn_proof_argument tzresult Lwt.t = + fun n inner_tc_context stk -> + match (Compare.Int.(n = 0), stk) with + | (true, rest) -> ( + non_terminal_recursion + ?type_logger + inner_tc_context + ctxt + ~legacy + code + rest + >>=? fun (judgement, ctxt) -> + Lwt.return + @@ + match judgement with + | Typed descr -> + ok @@ Dipn_proof_argument (Rest, (ctxt, descr), descr.aft) + | Failed _ -> + error (Fail_not_in_tail_position loc) ) + | (false, Item_t (v, rest, annot)) -> + make_proof_argument (n - 1) (add_dip v annot tc_context) rest + >|=? fun (Dipn_proof_argument (n', descr, aft')) -> + Dipn_proof_argument (Prefix n', descr, Item_t (v, aft', annot)) + | (_, _) -> + Lwt.return + ( serialize_stack_for_error ctxt stack + >>? fun (whole_stack, _ctxt) -> + error (Bad_stack (loc, I_DIP, 1, whole_stack)) ) + in + error_unexpected_annot loc result_annot + >>?= fun () -> + make_proof_argument n tc_context stack + >>=? fun (Dipn_proof_argument (n', (new_ctxt, descr), aft)) -> + (* TODO: which context should be used in the next line? new_ctxt or the old ctxt? *) + typed new_ctxt loc (Dipn (n, n', descr)) aft + | (Prim (loc, I_DIP, (([] | _ :: _ :: _ :: _) as l), _), _) -> + (* Technically, the arities 1 and 2 are allowed but the error only mentions 2. + However, DIP {code} is equivalent to DIP 1 {code} so hinting at an arity of 2 makes sense. *) + fail (Invalid_arity (loc, I_DIP, 2, List.length l)) + | (Prim (loc, I_FAILWITH, [], annot), Item_t (v, _rest, _)) -> + error_unexpected_annot loc annot + >>?= fun () -> + (if legacy then ok_unit else check_packable ~legacy:false loc v) + >>?= fun () -> + let descr aft = {loc; instr = Failwith v; bef = stack_ty; aft} in + log_stack ctxt loc stack_ty Empty_t + >>?= fun () -> return ctxt (Failed {descr}) + | (Prim (loc, I_NEVER, [], annot), Item_t (Never_t _, _rest, _)) -> + error_unexpected_annot loc annot + >>?= fun () -> + let descr aft = {loc; instr = Never; bef = stack_ty; aft} in + log_stack ctxt loc stack_ty Empty_t + >>?= fun () -> return ctxt (Failed {descr}) + (* timestamp operations *) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Timestamp_t tname, Item_t (Int_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Add_timestamp_to_seconds + (Item_t (Timestamp_t tname, rest, annot)) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Int_t _, Item_t (Timestamp_t tname, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Add_seconds_to_timestamp + (Item_t (Timestamp_t tname, rest, annot)) + | ( Prim (loc, I_SUB, [], annot), + Item_t (Timestamp_t tname, Item_t (Int_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Sub_timestamp_seconds + (Item_t (Timestamp_t tname, rest, annot)) + | ( Prim (loc, I_SUB, [], annot), + Item_t (Timestamp_t tn1, Item_t (Timestamp_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Diff_timestamps (Item_t (Int_t tname, rest, annot)) + (* string operations *) + | ( Prim (loc, I_CONCAT, [], annot), + Item_t (String_t tn1, Item_t (String_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Concat_string_pair (Item_t (String_t tname, rest, annot)) + | ( Prim (loc, I_CONCAT, [], annot), + Item_t (List_t (String_t tname, _), rest, list_annot) ) -> + parse_var_annot ~default:list_annot loc annot + >>?= fun annot -> + typed ctxt loc Concat_string (Item_t (String_t tname, rest, annot)) + | ( Prim (loc, I_SLICE, [], annot), + Item_t + ( Nat_t _, + Item_t (Nat_t _, Item_t (String_t tname, rest, string_annot), _), + _ ) ) -> + parse_var_annot + ~default:(gen_access_annot string_annot default_slice_annot) + loc + annot + >>?= fun annot -> + typed + ctxt + loc + Slice_string + (Item_t (Option_t (String_t tname, None), rest, annot)) + | (Prim (loc, I_SIZE, [], annot), Item_t (String_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc String_size (Item_t (Nat_t None, rest, annot)) + (* bytes operations *) + | ( Prim (loc, I_CONCAT, [], annot), + Item_t (Bytes_t tn1, Item_t (Bytes_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Concat_bytes_pair (Item_t (Bytes_t tname, rest, annot)) + | ( Prim (loc, I_CONCAT, [], annot), + Item_t (List_t (Bytes_t tname, _), rest, list_annot) ) -> + parse_var_annot ~default:list_annot loc annot + >>?= fun annot -> + typed ctxt loc Concat_bytes (Item_t (Bytes_t tname, rest, annot)) + | ( Prim (loc, I_SLICE, [], annot), + Item_t + ( Nat_t _, + Item_t (Nat_t _, Item_t (Bytes_t tname, rest, bytes_annot), _), + _ ) ) -> + parse_var_annot + ~default:(gen_access_annot bytes_annot default_slice_annot) + loc + annot + >>?= fun annot -> + typed + ctxt + loc + Slice_bytes + (Item_t (Option_t (Bytes_t tname, None), rest, annot)) + | (Prim (loc, I_SIZE, [], annot), Item_t (Bytes_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Bytes_size (Item_t (Nat_t None, rest, annot)) + (* currency operations *) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Mutez_t tn1, Item_t (Mutez_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Add_tez (Item_t (Mutez_t tname, rest, annot)) + | ( Prim (loc, I_SUB, [], annot), + Item_t (Mutez_t tn1, Item_t (Mutez_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Sub_tez (Item_t (Mutez_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Mutez_t tname, Item_t (Nat_t _, rest, _), _) ) -> + (* no type name check *) + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Mul_teznat (Item_t (Mutez_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Nat_t _, Item_t (Mutez_t tname, rest, _), _) ) -> + (* no type name check *) + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Mul_nattez (Item_t (Mutez_t tname, rest, annot)) + (* boolean operations *) + | ( Prim (loc, I_OR, [], annot), + Item_t (Bool_t tn1, Item_t (Bool_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> typed ctxt loc Or (Item_t (Bool_t tname, rest, annot)) + | ( Prim (loc, I_AND, [], annot), + Item_t (Bool_t tn1, Item_t (Bool_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> typed ctxt loc And (Item_t (Bool_t tname, rest, annot)) + | ( Prim (loc, I_XOR, [], annot), + Item_t (Bool_t tn1, Item_t (Bool_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> typed ctxt loc Xor (Item_t (Bool_t tname, rest, annot)) + | (Prim (loc, I_NOT, [], annot), Item_t (Bool_t tname, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> typed ctxt loc Not (Item_t (Bool_t tname, rest, annot)) + (* integer operations *) + | (Prim (loc, I_ABS, [], annot), Item_t (Int_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Abs_int (Item_t (Nat_t None, rest, annot)) + | (Prim (loc, I_ISNAT, [], annot), Item_t (Int_t _, rest, int_annot)) -> + parse_var_annot loc annot ~default:int_annot + >>?= fun annot -> + typed ctxt loc Is_nat (Item_t (Option_t (Nat_t None, None), rest, annot)) + | (Prim (loc, I_INT, [], annot), Item_t (Nat_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Int_nat (Item_t (Int_t None, rest, annot)) + | (Prim (loc, I_NEG, [], annot), Item_t (Int_t tname, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Neg_int (Item_t (Int_t tname, rest, annot)) + | (Prim (loc, I_NEG, [], annot), Item_t (Nat_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Neg_nat (Item_t (Int_t None, rest, annot)) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Int_t tn1, Item_t (Int_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Add_intint (Item_t (Int_t tname, rest, annot)) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Int_t tname, Item_t (Nat_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Add_intnat (Item_t (Int_t tname, rest, annot)) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Nat_t _, Item_t (Int_t tname, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Add_natint (Item_t (Int_t tname, rest, annot)) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Nat_t tn1, Item_t (Nat_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Add_natnat (Item_t (Nat_t tname, rest, annot)) + | ( Prim (loc, I_SUB, [], annot), + Item_t (Int_t tn1, Item_t (Int_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Sub_int (Item_t (Int_t tname, rest, annot)) + | ( Prim (loc, I_SUB, [], annot), + Item_t (Int_t tname, Item_t (Nat_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Sub_int (Item_t (Int_t tname, rest, annot)) + | ( Prim (loc, I_SUB, [], annot), + Item_t (Nat_t _, Item_t (Int_t tname, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Sub_int (Item_t (Int_t tname, rest, annot)) + | ( Prim (loc, I_SUB, [], annot), + Item_t (Nat_t tn1, Item_t (Nat_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun _tname -> + typed ctxt loc Sub_int (Item_t (Int_t None, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Int_t tn1, Item_t (Int_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Mul_intint (Item_t (Int_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Int_t tname, Item_t (Nat_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Mul_intnat (Item_t (Int_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Nat_t _, Item_t (Int_t tname, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Mul_natint (Item_t (Int_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Nat_t tn1, Item_t (Nat_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Mul_natnat (Item_t (Nat_t tname, rest, annot)) + | ( Prim (loc, I_EDIV, [], annot), + Item_t (Mutez_t tname, Item_t (Nat_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Ediv_teznat + (Item_t + ( Option_t + ( Pair_t + ( (Mutez_t tname, None, None), + (Mutez_t tname, None, None), + None ), + None ), + rest, + annot )) + | ( Prim (loc, I_EDIV, [], annot), + Item_t (Mutez_t tn1, Item_t (Mutez_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed + ctxt + loc + Ediv_tez + (Item_t + ( Option_t + ( Pair_t + ((Nat_t None, None, None), (Mutez_t tname, None, None), None), + None ), + rest, + annot )) + | ( Prim (loc, I_EDIV, [], annot), + Item_t (Int_t tn1, Item_t (Int_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed + ctxt + loc + Ediv_intint + (Item_t + ( Option_t + ( Pair_t + ((Int_t tname, None, None), (Nat_t None, None, None), None), + None ), + rest, + annot )) + | ( Prim (loc, I_EDIV, [], annot), + Item_t (Int_t tname, Item_t (Nat_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Ediv_intnat + (Item_t + ( Option_t + ( Pair_t + ((Int_t tname, None, None), (Nat_t None, None, None), None), + None ), + rest, + annot )) + | ( Prim (loc, I_EDIV, [], annot), + Item_t (Nat_t tname, Item_t (Int_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Ediv_natint + (Item_t + ( Option_t + ( Pair_t + ((Int_t None, None, None), (Nat_t tname, None, None), None), + None ), + rest, + annot )) + | ( Prim (loc, I_EDIV, [], annot), + Item_t (Nat_t tn1, Item_t (Nat_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed + ctxt + loc + Ediv_natnat + (Item_t + ( Option_t + ( Pair_t + ((Nat_t tname, None, None), (Nat_t tname, None, None), None), + None ), + rest, + annot )) + | ( Prim (loc, I_LSL, [], annot), + Item_t (Nat_t tn1, Item_t (Nat_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Lsl_nat (Item_t (Nat_t tname, rest, annot)) + | ( Prim (loc, I_LSR, [], annot), + Item_t (Nat_t tn1, Item_t (Nat_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Lsr_nat (Item_t (Nat_t tname, rest, annot)) + | ( Prim (loc, I_OR, [], annot), + Item_t (Nat_t tn1, Item_t (Nat_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Or_nat (Item_t (Nat_t tname, rest, annot)) + | ( Prim (loc, I_AND, [], annot), + Item_t (Nat_t tn1, Item_t (Nat_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc And_nat (Item_t (Nat_t tname, rest, annot)) + | ( Prim (loc, I_AND, [], annot), + Item_t (Int_t _, Item_t (Nat_t tname, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc And_int_nat (Item_t (Nat_t tname, rest, annot)) + | ( Prim (loc, I_XOR, [], annot), + Item_t (Nat_t tn1, Item_t (Nat_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed ctxt loc Xor_nat (Item_t (Nat_t tname, rest, annot)) + | (Prim (loc, I_NOT, [], annot), Item_t (Int_t tname, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Not_int (Item_t (Int_t tname, rest, annot)) + | (Prim (loc, I_NOT, [], annot), Item_t (Nat_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Not_nat (Item_t (Int_t None, rest, annot)) + (* comparison *) + | (Prim (loc, I_COMPARE, [], annot), Item_t (t1, Item_t (t2, rest, _), _)) -> + parse_var_annot loc annot + >>?= fun annot -> + check_item_ty ctxt t1 t2 loc I_COMPARE 1 2 + >>?= fun (Eq, t, ctxt) -> + comparable_ty_of_ty ctxt loc t + >>?= fun (key, ctxt) -> + typed ctxt loc (Compare key) (Item_t (Int_t None, rest, annot)) + (* comparators *) + | (Prim (loc, I_EQ, [], annot), Item_t (Int_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> typed ctxt loc Eq (Item_t (Bool_t None, rest, annot)) + | (Prim (loc, I_NEQ, [], annot), Item_t (Int_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> typed ctxt loc Neq (Item_t (Bool_t None, rest, annot)) + | (Prim (loc, I_LT, [], annot), Item_t (Int_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> typed ctxt loc Lt (Item_t (Bool_t None, rest, annot)) + | (Prim (loc, I_GT, [], annot), Item_t (Int_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> typed ctxt loc Gt (Item_t (Bool_t None, rest, annot)) + | (Prim (loc, I_LE, [], annot), Item_t (Int_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> typed ctxt loc Le (Item_t (Bool_t None, rest, annot)) + | (Prim (loc, I_GE, [], annot), Item_t (Int_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> typed ctxt loc Ge (Item_t (Bool_t None, rest, annot)) + (* annotations *) + | (Prim (loc, I_CAST, [cast_t], annot), Item_t (t, stack, item_annot)) -> + parse_var_annot loc annot ~default:item_annot + >>?= fun annot -> + parse_any_ty ctxt ~legacy cast_t + >>?= fun (Ex_ty cast_t, ctxt) -> + merge_types ~legacy ctxt loc cast_t t + >>?= fun (Eq, _, ctxt) -> + typed ctxt loc Nop (Item_t (cast_t, stack, annot)) + | (Prim (loc, I_RENAME, [], annot), Item_t (t, stack, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + (* can erase annot *) + typed ctxt loc Nop (Item_t (t, stack, annot)) + (* packing *) + | (Prim (loc, I_PACK, [], annot), Item_t (t, rest, unpacked_annot)) -> + check_packable + ~legacy:true + (* allow to pack contracts for hash/signature checks *) loc + t + >>?= fun () -> + parse_var_annot + loc + annot + ~default:(gen_access_annot unpacked_annot default_pack_annot) + >>?= fun annot -> + typed ctxt loc (Pack t) (Item_t (Bytes_t None, rest, annot)) + | (Prim (loc, I_UNPACK, [ty], annot), Item_t (Bytes_t _, rest, packed_annot)) + -> + parse_packable_ty ctxt ~legacy ty + >>?= fun (Ex_ty t, ctxt) -> + parse_var_type_annot loc annot + >>?= fun (annot, ty_name) -> + let annot = + default_annot + annot + ~default:(gen_access_annot packed_annot default_unpack_annot) + in + typed ctxt loc (Unpack t) (Item_t (Option_t (t, ty_name), rest, annot)) + (* protocol *) + | ( Prim (loc, I_ADDRESS, [], annot), + Item_t (Contract_t _, rest, contract_annot) ) -> + parse_var_annot + loc + annot + ~default:(gen_access_annot contract_annot default_addr_annot) + >>?= fun annot -> + typed ctxt loc Address (Item_t (Address_t None, rest, annot)) + | ( Prim (loc, I_CONTRACT, [ty], annot), + Item_t (Address_t _, rest, addr_annot) ) -> + parse_parameter_ty ctxt ~legacy ty + >>?= fun (Ex_ty t, ctxt) -> + parse_entrypoint_annot + loc + annot + ~default:(gen_access_annot addr_annot default_contract_annot) + >>?= fun (annot, entrypoint) -> + ( match entrypoint with + | None -> + Ok "default" + | Some (Field_annot "default") -> + error (Unexpected_annotation loc) + | Some (Field_annot entrypoint) -> + if Compare.Int.(String.length entrypoint > 31) then + error (Entrypoint_name_too_long entrypoint) + else Ok entrypoint ) + >>?= fun entrypoint -> + typed + ctxt + loc + (Contract (t, entrypoint)) + (Item_t (Option_t (Contract_t (t, None), None), rest, annot)) + | ( Prim (loc, I_TRANSFER_TOKENS, [], annot), + Item_t (p, Item_t (Mutez_t _, Item_t (Contract_t (cp, _), rest, _), _), _) + ) -> + check_item_ty ctxt p cp loc I_TRANSFER_TOKENS 1 4 + >>?= fun (Eq, _, ctxt) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Transfer_tokens (Item_t (Operation_t None, rest, annot)) + | ( Prim (loc, I_SET_DELEGATE, [], annot), + Item_t (Option_t (Key_hash_t _, _), rest, _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Set_delegate (Item_t (Operation_t None, rest, annot)) + | (Prim (_, I_CREATE_ACCOUNT, _, _), _) -> + fail (Deprecated_instruction I_CREATE_ACCOUNT) + | (Prim (loc, I_IMPLICIT_ACCOUNT, [], annot), Item_t (Key_hash_t _, rest, _)) + -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Implicit_account + (Item_t (Contract_t (Unit_t None, None), rest, annot)) + | ( Prim (loc, I_CREATE_CONTRACT, [(Seq _ as code)], annot), + Item_t + ( Option_t (Key_hash_t _, _), + Item_t (Mutez_t _, Item_t (ginit, rest, _), _), + _ ) ) -> + parse_two_var_annot loc annot + >>?= fun (op_annot, addr_annot) -> + let canonical_code = fst @@ Micheline.extract_locations code in + parse_toplevel ~legacy canonical_code + >>?= fun (arg_type, storage_type, code_field, root_name) -> + record_trace + (Ill_formed_type (Some "parameter", canonical_code, location arg_type)) + (parse_parameter_ty ctxt ~legacy arg_type) + >>?= fun (Ex_ty arg_type, ctxt) -> + (if legacy then ok_unit else well_formed_entrypoints ~root_name arg_type) + >>?= fun () -> + record_trace + (Ill_formed_type (Some "storage", canonical_code, location storage_type)) + (parse_storage_ty ctxt ~legacy storage_type) + >>?= fun (Ex_ty storage_type, ctxt) -> + let arg_annot = + default_annot + (type_to_var_annot (name_of_ty arg_type)) + ~default:default_param_annot + in + let storage_annot = + default_annot + (type_to_var_annot (name_of_ty storage_type)) + ~default:default_storage_annot + in + let arg_type_full = + Pair_t + ( (arg_type, None, arg_annot), + (storage_type, None, storage_annot), + None ) + in + let ret_type_full = + Pair_t + ( (List_t (Operation_t None, None), None, None), + (storage_type, None, None), + None ) + in + trace + (Ill_typed_contract (canonical_code, [])) + (parse_returning + (Toplevel + { + storage_type; + param_type = arg_type; + root_name; + legacy_create_contract_literal = false; + }) + ctxt + ~legacy + ?type_logger + ~stack_depth + (arg_type_full, None) + ret_type_full + code_field) + >>=? fun ( ( Lam + ( { bef = Item_t (arg, Empty_t, _); + aft = Item_t (ret, Empty_t, _); + _ }, + _ ) as lambda ), + ctxt ) -> + merge_types ~legacy ctxt loc arg arg_type_full + >>?= fun (Eq, _, ctxt) -> + merge_types ~legacy ctxt loc ret ret_type_full + >>?= fun (Eq, _, ctxt) -> + merge_types ~legacy ctxt loc storage_type ginit + >>?= fun (Eq, _, ctxt) -> + typed + ctxt + loc + (Create_contract (storage_type, arg_type, lambda, root_name)) + (Item_t + ( Operation_t None, + Item_t (Address_t None, rest, addr_annot), + op_annot )) + | (Prim (loc, I_NOW, [], annot), stack) -> + parse_var_annot loc annot ~default:default_now_annot + >>?= fun annot -> + typed ctxt loc Now (Item_t (Timestamp_t None, stack, annot)) + | (Prim (loc, I_AMOUNT, [], annot), stack) -> + parse_var_annot loc annot ~default:default_amount_annot + >>?= fun annot -> + typed ctxt loc Amount (Item_t (Mutez_t None, stack, annot)) + | (Prim (loc, I_CHAIN_ID, [], annot), stack) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc ChainId (Item_t (Chain_id_t None, stack, annot)) + | (Prim (loc, I_BALANCE, [], annot), stack) -> + parse_var_annot loc annot ~default:default_balance_annot + >>?= fun annot -> + typed ctxt loc Balance (Item_t (Mutez_t None, stack, annot)) + | (Prim (loc, I_LEVEL, [], annot), stack) -> + parse_var_annot loc annot ~default:default_level_annot + >>?= fun annot -> + typed ctxt loc Level (Item_t (Nat_t None, stack, annot)) + | (Prim (loc, I_VOTING_POWER, [], annot), Item_t (Key_hash_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Voting_power (Item_t (Nat_t None, rest, annot)) + | (Prim (loc, I_TOTAL_VOTING_POWER, [], annot), stack) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Total_voting_power (Item_t (Nat_t None, stack, annot)) + | (Prim (_, I_STEPS_TO_QUOTA, _, _), _) -> + fail (Deprecated_instruction I_STEPS_TO_QUOTA) + | (Prim (loc, I_SOURCE, [], annot), stack) -> + parse_var_annot loc annot ~default:default_source_annot + >>?= fun annot -> + typed ctxt loc Source (Item_t (Address_t None, stack, annot)) + | (Prim (loc, I_SENDER, [], annot), stack) -> + parse_var_annot loc annot ~default:default_sender_annot + >>?= fun annot -> + typed ctxt loc Sender (Item_t (Address_t None, stack, annot)) + | (Prim (loc, I_SELF, [], annot), stack) -> + Lwt.return + ( parse_entrypoint_annot loc annot ~default:default_self_annot + >>? fun (annot, entrypoint) -> + let entrypoint = + Option.fold + ~some:(fun (Field_annot annot) -> annot) + ~none:"default" + entrypoint + in + let rec get_toplevel_type : + tc_context -> (bef judgement * context) tzresult = function + | Lambda -> + error (Self_in_lambda loc) + | Dip (_, prev) -> + get_toplevel_type prev + | Toplevel + {param_type; root_name; legacy_create_contract_literal = false} + -> + find_entrypoint param_type ~root_name entrypoint + >>? fun (_, Ex_ty param_type) -> + typed_no_lwt + ctxt + loc + (Self (param_type, entrypoint)) + (Item_t (Contract_t (param_type, None), stack, annot)) + | Toplevel + {param_type; root_name = _; legacy_create_contract_literal = true} + -> + typed_no_lwt + ctxt + loc + (Self (param_type, "default")) + (Item_t (Contract_t (param_type, None), stack, annot)) + in + get_toplevel_type tc_context ) + | (Prim (loc, I_SELF_ADDRESS, [], annot), stack) -> + parse_var_annot loc annot ~default:default_self_annot + >>?= fun annot -> + typed ctxt loc Self_address (Item_t (Address_t None, stack, annot)) + (* cryptography *) + | (Prim (loc, I_HASH_KEY, [], annot), Item_t (Key_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Hash_key (Item_t (Key_hash_t None, rest, annot)) + | ( Prim (loc, I_CHECK_SIGNATURE, [], annot), + Item_t + (Key_t _, Item_t (Signature_t _, Item_t (Bytes_t _, rest, _), _), _) ) + -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Check_signature (Item_t (Bool_t None, rest, annot)) + | (Prim (loc, I_BLAKE2B, [], annot), Item_t (Bytes_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Blake2b (Item_t (Bytes_t None, rest, annot)) + | (Prim (loc, I_SHA256, [], annot), Item_t (Bytes_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Sha256 (Item_t (Bytes_t None, rest, annot)) + | (Prim (loc, I_SHA512, [], annot), Item_t (Bytes_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Sha512 (Item_t (Bytes_t None, rest, annot)) + | (Prim (loc, I_KECCAK, [], annot), Item_t (Bytes_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Keccak (Item_t (Bytes_t None, rest, annot)) + | (Prim (loc, I_SHA3, [], annot), Item_t (Bytes_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Sha3 (Item_t (Bytes_t None, rest, annot)) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Bls12_381_g1_t tn1, Item_t (Bls12_381_g1_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed + ctxt + loc + Add_bls12_381_g1 + (Item_t (Bls12_381_g1_t tname, rest, annot)) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Bls12_381_g2_t tn1, Item_t (Bls12_381_g2_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed + ctxt + loc + Add_bls12_381_g2 + (Item_t (Bls12_381_g2_t tname, rest, annot)) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Bls12_381_fr_t tn1, Item_t (Bls12_381_fr_t tn2, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + merge_type_annot ~legacy tn1 tn2 + >>?= fun tname -> + typed + ctxt + loc + Add_bls12_381_fr + (Item_t (Bls12_381_fr_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Bls12_381_g1_t tname, Item_t (Bls12_381_fr_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Mul_bls12_381_g1 + (Item_t (Bls12_381_g1_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Bls12_381_g2_t tname, Item_t (Bls12_381_fr_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Mul_bls12_381_g2 + (Item_t (Bls12_381_g2_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Bls12_381_fr_t tname, Item_t (Bls12_381_fr_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Mul_bls12_381_fr + (Item_t (Bls12_381_fr_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Nat_t tname, Item_t (Bls12_381_fr_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Mul_bls12_381_fr_z + (Item_t (Bls12_381_fr_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Int_t tname, Item_t (Bls12_381_fr_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Mul_bls12_381_fr_z + (Item_t (Bls12_381_fr_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Bls12_381_fr_t tname, Item_t (Int_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Mul_bls12_381_z_fr + (Item_t (Bls12_381_fr_t tname, rest, annot)) + | ( Prim (loc, I_MUL, [], annot), + Item_t (Bls12_381_fr_t tname, Item_t (Nat_t _, rest, _), _) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Mul_bls12_381_z_fr + (Item_t (Bls12_381_fr_t tname, rest, annot)) + | (Prim (loc, I_INT, [], annot), Item_t (Bls12_381_fr_t _, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed ctxt loc Int_bls12_381_fr (Item_t (Int_t None, rest, annot)) + | (Prim (loc, I_NEG, [], annot), Item_t (Bls12_381_g1_t tname, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Neg_bls12_381_g1 + (Item_t (Bls12_381_g1_t tname, rest, annot)) + | (Prim (loc, I_NEG, [], annot), Item_t (Bls12_381_g2_t tname, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Neg_bls12_381_g2 + (Item_t (Bls12_381_g2_t tname, rest, annot)) + | (Prim (loc, I_NEG, [], annot), Item_t (Bls12_381_fr_t tname, rest, _)) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Neg_bls12_381_fr + (Item_t (Bls12_381_fr_t tname, rest, annot)) + | ( Prim (loc, I_PAIRING_CHECK, [], annot), + Item_t + ( List_t + (Pair_t ((Bls12_381_g1_t _, _, _), (Bls12_381_g2_t _, _, _), _), _), + rest, + _ ) ) -> + parse_var_annot loc annot + >>?= fun annot -> + typed + ctxt + loc + Pairing_check_bls12_381 + (Item_t (Bool_t None, rest, annot)) + (* Tickets *) + | (Prim (loc, I_TICKET, [], annot), Item_t (t, Item_t (Nat_t _, rest, _), _)) + -> + parse_var_annot loc annot + >>?= fun annot -> + comparable_ty_of_ty ctxt loc t + >>?= fun (ty, ctxt) -> + typed ctxt loc Ticket (Item_t (Ticket_t (ty, None), rest, annot)) + | ( Prim (loc, I_READ_TICKET, [], annot), + (Item_t (Ticket_t (t, _), _, _) as full_stack) ) -> + parse_var_annot loc annot + >>?= fun annot -> + let () = check_dupable_comparable_ty t in + let result = ty_of_comparable_ty @@ opened_ticket_type t in + typed ctxt loc Read_ticket (Item_t (result, full_stack, annot)) + | ( Prim (loc, I_SPLIT_TICKET, [], annot), + Item_t + ( (Ticket_t (t, _) as ticket_t), + Item_t + (Pair_t ((Nat_t _, fa_a, a_a), (Nat_t _, fa_b, a_b), _), rest, _), + _ ) ) -> + parse_var_annot loc annot + >>?= fun annot -> + let () = check_dupable_comparable_ty t in + let result = + Option_t + (Pair_t ((ticket_t, fa_a, a_a), (ticket_t, fa_b, a_b), None), None) + in + typed ctxt loc Split_ticket (Item_t (result, rest, annot)) + | ( Prim (loc, I_JOIN_TICKETS, [], annot), + Item_t + ( Pair_t (((Ticket_t _ as ty_a), _, _), ((Ticket_t _ as ty_b), _, _), _), + rest, + _ ) ) -> ( + parse_var_annot loc annot + >>?= fun annot -> + merge_types ~legacy ctxt loc ty_a ty_b + >>?= fun (Eq, ty, ctxt) -> + match ty with + | Ticket_t (contents_ty, _) -> + typed + ctxt + loc + (Join_tickets contents_ty) + (Item_t (Option_t (ty, None), rest, annot)) + | _ -> + (* TODO: fix injectivity of types *) assert false ) + (* Primitive parsing errors *) + | ( Prim + ( loc, + ( ( I_DUP + | I_SWAP + | I_SOME + | I_UNIT + | I_PAIR + | I_UNPAIR + | I_CAR + | I_CDR + | I_CONS + | I_CONCAT + | I_SLICE + | I_MEM + | I_UPDATE + | I_GET + | I_EXEC + | I_FAILWITH + | I_SIZE + | I_ADD + | I_SUB + | I_MUL + | I_EDIV + | I_OR + | I_AND + | I_XOR + | I_NOT + | I_ABS + | I_NEG + | I_LSL + | I_LSR + | I_COMPARE + | I_EQ + | I_NEQ + | I_LT + | I_GT + | I_LE + | I_GE + | I_TRANSFER_TOKENS + | I_SET_DELEGATE + | I_NOW + | I_IMPLICIT_ACCOUNT + | I_AMOUNT + | I_BALANCE + | I_LEVEL + | I_CHECK_SIGNATURE + | I_HASH_KEY + | I_SOURCE + | I_SENDER + | I_BLAKE2B + | I_SHA256 + | I_SHA512 + | I_ADDRESS + | I_RENAME + | I_PACK + | I_ISNAT + | I_INT + | I_SELF + | I_CHAIN_ID + | I_NEVER + | I_VOTING_POWER + | I_TOTAL_VOTING_POWER + | I_KECCAK + | I_SHA3 + | I_PAIRING_CHECK + | I_TICKET + | I_READ_TICKET + | I_SPLIT_TICKET + | I_JOIN_TICKETS ) as name ), + (_ :: _ as l), + _ ), + _ ) -> + fail (Invalid_arity (loc, name, 0, List.length l)) + | ( Prim + ( loc, + ( ( I_NONE + | I_LEFT + | I_RIGHT + | I_NIL + | I_MAP + | I_ITER + | I_EMPTY_SET + | I_LOOP + | I_LOOP_LEFT + | I_CONTRACT + | I_CAST + | I_UNPACK + | I_CREATE_CONTRACT ) as name ), + (([] | _ :: _ :: _) as l), + _ ), + _ ) -> + fail (Invalid_arity (loc, name, 1, List.length l)) + | ( Prim + ( loc, + ( ( I_PUSH + | I_IF_NONE + | I_IF_LEFT + | I_IF_CONS + | I_EMPTY_MAP + | I_EMPTY_BIG_MAP + | I_IF ) as name ), + (([] | [_] | _ :: _ :: _ :: _) as l), + _ ), + _ ) -> + fail (Invalid_arity (loc, name, 2, List.length l)) + | ( Prim + (loc, I_LAMBDA, (([] | [_] | [_; _] | _ :: _ :: _ :: _ :: _) as l), _), + _ ) -> + fail (Invalid_arity (loc, I_LAMBDA, 3, List.length l)) + (* Stack errors *) + | ( Prim + ( loc, + ( ( I_ADD + | I_SUB + | I_MUL + | I_EDIV + | I_AND + | I_OR + | I_XOR + | I_LSL + | I_LSR + | I_CONCAT + | I_PAIRING_CHECK ) as name ), + [], + _ ), + Item_t (ta, Item_t (tb, _, _), _) ) -> + serialize_ty_for_error ctxt ta + >>?= fun (ta, ctxt) -> + serialize_ty_for_error ctxt tb + >>?= fun (tb, _ctxt) -> fail (Undefined_binop (loc, name, ta, tb)) + | ( Prim + ( loc, + ( ( I_NEG + | I_ABS + | I_NOT + | I_SIZE + | I_EQ + | I_NEQ + | I_LT + | I_GT + | I_LE + | I_GE + (* CONCAT is both unary and binary; this case can only be triggered + on a singleton stack *) + | I_CONCAT ) as name ), + [], + _ ), + Item_t (t, _, _) ) -> + serialize_ty_for_error ctxt t + >>?= fun (t, _ctxt) -> fail (Undefined_unop (loc, name, t)) + | (Prim (loc, ((I_UPDATE | I_SLICE) as name), [], _), stack) -> + Lwt.return + ( serialize_stack_for_error ctxt stack + >>? fun (stack, _ctxt) -> error (Bad_stack (loc, name, 3, stack)) ) + | (Prim (loc, I_CREATE_CONTRACT, _, _), stack) -> + serialize_stack_for_error ctxt stack + >>?= fun (stack, _ctxt) -> + fail (Bad_stack (loc, I_CREATE_CONTRACT, 7, stack)) + | (Prim (loc, I_TRANSFER_TOKENS, [], _), stack) -> + Lwt.return + ( serialize_stack_for_error ctxt stack + >>? fun (stack, _ctxt) -> + error (Bad_stack (loc, I_TRANSFER_TOKENS, 4, stack)) ) + | ( Prim + ( loc, + ( ( I_DROP + | I_DUP + | I_CAR + | I_CDR + | I_UNPAIR + | I_SOME + | I_BLAKE2B + | I_SHA256 + | I_SHA512 + | I_DIP + | I_IF_NONE + | I_LEFT + | I_RIGHT + | I_IF_LEFT + | I_IF + | I_LOOP + | I_IF_CONS + | I_IMPLICIT_ACCOUNT + | I_NEG + | I_ABS + | I_INT + | I_NOT + | I_HASH_KEY + | I_EQ + | I_NEQ + | I_LT + | I_GT + | I_LE + | I_GE + | I_SIZE + | I_FAILWITH + | I_RENAME + | I_PACK + | I_ISNAT + | I_ADDRESS + | I_SET_DELEGATE + | I_CAST + | I_MAP + | I_ITER + | I_LOOP_LEFT + | I_UNPACK + | I_CONTRACT + | I_NEVER + | I_KECCAK + | I_SHA3 + | I_READ_TICKET + | I_JOIN_TICKETS ) as name ), + _, + _ ), + stack ) -> + Lwt.return + ( serialize_stack_for_error ctxt stack + >>? fun (stack, _ctxt) -> error (Bad_stack (loc, name, 1, stack)) ) + | ( Prim + ( loc, + ( ( I_SWAP + | I_PAIR + | I_CONS + | I_GET + | I_MEM + | I_EXEC + | I_CHECK_SIGNATURE + | I_ADD + | I_SUB + | I_MUL + | I_EDIV + | I_AND + | I_OR + | I_XOR + | I_LSL + | I_LSR + | I_COMPARE + | I_PAIRING_CHECK + | I_TICKET + | I_SPLIT_TICKET ) as name ), + _, + _ ), + stack ) -> + Lwt.return + ( serialize_stack_for_error ctxt stack + >>? fun (stack, _ctxt) -> error (Bad_stack (loc, name, 2, stack)) ) + (* Generic parsing errors *) + | (expr, _) -> + fail + @@ unexpected + expr + [Seq_kind] + Instr_namespace + [ I_DROP; + I_DUP; + I_DIG; + I_DUG; + I_SWAP; + I_SOME; + I_UNIT; + I_PAIR; + I_UNPAIR; + I_CAR; + I_CDR; + I_CONS; + I_MEM; + I_UPDATE; + I_MAP; + I_ITER; + I_GET; + I_GET_AND_UPDATE; + I_EXEC; + I_FAILWITH; + I_SIZE; + I_CONCAT; + I_ADD; + I_SUB; + I_MUL; + I_EDIV; + I_OR; + I_AND; + I_XOR; + I_NOT; + I_ABS; + I_INT; + I_NEG; + I_LSL; + I_LSR; + I_COMPARE; + I_EQ; + I_NEQ; + I_LT; + I_GT; + I_LE; + I_GE; + I_TRANSFER_TOKENS; + I_CREATE_CONTRACT; + I_NOW; + I_AMOUNT; + I_BALANCE; + I_LEVEL; + I_IMPLICIT_ACCOUNT; + I_CHECK_SIGNATURE; + I_BLAKE2B; + I_SHA256; + I_SHA512; + I_HASH_KEY; + I_PUSH; + I_NONE; + I_LEFT; + I_RIGHT; + I_NIL; + I_EMPTY_SET; + I_DIP; + I_LOOP; + I_IF_NONE; + I_IF_LEFT; + I_IF_CONS; + I_EMPTY_MAP; + I_EMPTY_BIG_MAP; + I_IF; + I_SOURCE; + I_SENDER; + I_SELF; + I_SELF_ADDRESS; + I_LAMBDA; + I_NEVER; + I_VOTING_POWER; + I_TOTAL_VOTING_POWER; + I_KECCAK; + I_SHA3; + I_PAIRING_CHECK; + I_SAPLING_EMPTY_STATE; + I_SAPLING_VERIFY_UPDATE; + I_TICKET; + I_READ_TICKET; + I_SPLIT_TICKET; + I_JOIN_TICKETS ] + +and parse_contract : + type arg. + legacy:bool -> + context -> + Script.location -> + arg ty -> + Contract.t -> + entrypoint:string -> + (context * arg typed_contract) tzresult Lwt.t = + fun ~legacy ctxt loc arg contract ~entrypoint -> + Gas.consume ctxt Typecheck_costs.contract_exists + >>?= fun ctxt -> + Contract.exists ctxt contract + >>=? function + | false -> + fail (Invalid_contract (loc, contract)) + | true -> ( + trace (Invalid_contract (loc, contract)) + @@ Contract.get_script_code ctxt contract + >>=? fun (ctxt, code) -> + Lwt.return + @@ + match code with + | None -> ( + ty_eq ctxt loc arg (Unit_t None) + >>? fun (Eq, ctxt) -> + match entrypoint with + | "default" -> + let contract : arg typed_contract = + (arg, (contract, entrypoint)) + in + ok (ctxt, contract) + | entrypoint -> + error (No_such_entrypoint entrypoint) ) + | Some code -> + Script.force_decode_in_context ctxt code + >>? fun (code, ctxt) -> + parse_toplevel ~legacy:true code + >>? fun (arg_type, _, _, root_name) -> + parse_parameter_ty ctxt ~legacy:true arg_type + >>? fun (Ex_ty targ, ctxt) -> + find_entrypoint_for_type + ~legacy + ~full:targ + ~expected:arg + ~root_name + entrypoint + ctxt + loc + >|? fun (ctxt, entrypoint, arg) -> + let contract : arg typed_contract = (arg, (contract, entrypoint)) in + (ctxt, contract) ) + +(* Same as the one above, but does not fail when the contact is missing or + if the expected type doesn't match the actual one. In that case None is + returned and some overapproximation of the typechecking gas is consumed. + This can still fail on gas exhaustion. *) +and parse_contract_for_script : + type arg. + context -> + Script.location -> + arg ty -> + Contract.t -> + entrypoint:string -> + (context * arg typed_contract option) tzresult Lwt.t = + fun ctxt loc arg contract ~entrypoint -> + Gas.consume ctxt Typecheck_costs.contract_exists + >>?= fun ctxt -> + match (Contract.is_implicit contract, entrypoint) with + | (Some _, "default") -> + (* An implicit account on the "default" entrypoint always exists and has type unit. *) + Lwt.return + ( match ty_eq ctxt loc arg (Unit_t None) with + | Ok (Eq, ctxt) -> + let contract : arg typed_contract = + (arg, (contract, entrypoint)) + in + ok (ctxt, Some contract) + | Error _ -> + Gas.consume ctxt Typecheck_costs.parse_instr_cycle + >>? fun ctxt -> ok (ctxt, None) ) + | (Some _, _) -> + Lwt.return + ( Gas.consume ctxt Typecheck_costs.parse_instr_cycle + >|? fun ctxt -> + (* An implicit account on any other entrypoint is not a valid contract. *) + (ctxt, None) ) + | (None, _) -> ( + (* Originated account *) + Contract.exists ctxt contract + >>=? function + | false -> + return (ctxt, None) + | true -> ( + trace (Invalid_contract (loc, contract)) + @@ Contract.get_script_code ctxt contract + >>=? fun (ctxt, code) -> + match code with + | None -> + (* Since protocol 005, we have the invariant that all originated accounts have code *) + assert false + | Some code -> + Lwt.return + ( Script.force_decode_in_context ctxt code + >>? fun (code, ctxt) -> + (* can only fail because of gas *) + match parse_toplevel ~legacy:true code with + | Error _ -> + error (Invalid_contract (loc, contract)) + | Ok (arg_type, _, _, root_name) -> ( + match parse_parameter_ty ctxt ~legacy:true arg_type with + | Error _ -> + error (Invalid_contract (loc, contract)) + | Ok (Ex_ty targ, ctxt) -> ( + match + find_entrypoint_for_type + ~legacy:false + ~full:targ + ~expected:arg + ~root_name + entrypoint + ctxt + loc + >|? fun (ctxt, entrypoint, arg) -> + let contract : arg typed_contract = + (arg, (contract, entrypoint)) + in + (ctxt, Some contract) + with + | Ok res -> + ok res + | Error _ -> + (* overapproximation by checking if targ = targ, + can only fail because of gas *) + merge_types ~legacy:false ctxt loc targ targ + >|? fun (Eq, _, ctxt) -> (ctxt, None) ) ) ) ) ) + +and parse_toplevel : + legacy:bool -> + Script.expr -> + (Script.node * Script.node * Script.node * field_annot option) tzresult = + fun ~legacy toplevel -> + record_trace (Ill_typed_contract (toplevel, [])) + @@ + match root toplevel with + | Int (loc, _) -> + error (Invalid_kind (loc, [Seq_kind], Int_kind)) + | String (loc, _) -> + error (Invalid_kind (loc, [Seq_kind], String_kind)) + | Bytes (loc, _) -> + error (Invalid_kind (loc, [Seq_kind], Bytes_kind)) + | Prim (loc, _, _, _) -> + error (Invalid_kind (loc, [Seq_kind], Prim_kind)) + | Seq (_, fields) -> ( + let rec find_fields p s c fields = + match fields with + | [] -> + ok (p, s, c) + | Int (loc, _) :: _ -> + error (Invalid_kind (loc, [Prim_kind], Int_kind)) + | String (loc, _) :: _ -> + error (Invalid_kind (loc, [Prim_kind], String_kind)) + | Bytes (loc, _) :: _ -> + error (Invalid_kind (loc, [Prim_kind], Bytes_kind)) + | Seq (loc, _) :: _ -> + error (Invalid_kind (loc, [Prim_kind], Seq_kind)) + | Prim (loc, K_parameter, [arg], annot) :: rest -> ( + match p with + | None -> + find_fields (Some (arg, loc, annot)) s c rest + | Some _ -> + error (Duplicate_field (loc, K_parameter)) ) + | Prim (loc, K_storage, [arg], annot) :: rest -> ( + match s with + | None -> + find_fields p (Some (arg, loc, annot)) c rest + | Some _ -> + error (Duplicate_field (loc, K_storage)) ) + | Prim (loc, K_code, [arg], annot) :: rest -> ( + match c with + | None -> + find_fields p s (Some (arg, loc, annot)) rest + | Some _ -> + error (Duplicate_field (loc, K_code)) ) + | Prim (loc, ((K_parameter | K_storage | K_code) as name), args, _) + :: _ -> + error (Invalid_arity (loc, name, 1, List.length args)) + | Prim (loc, name, _, _) :: _ -> + let allowed = [K_parameter; K_storage; K_code] in + error (Invalid_primitive (loc, allowed, name)) + in + find_fields None None None fields + >>? function + | (None, _, _) -> + error (Missing_field K_parameter) + | (Some _, None, _) -> + error (Missing_field K_storage) + | (Some _, Some _, None) -> + error (Missing_field K_code) + | (Some (p, ploc, pannot), Some (s, sloc, sannot), Some (c, cloc, carrot)) + -> + let maybe_root_name = + (* root name can be attached to either the parameter + primitive or the toplevel constructor *) + Script_ir_annot.extract_field_annot p + >>? fun (p, root_name) -> + match root_name with + | Some _ -> + ok (p, pannot, root_name) + | None -> ( + match pannot with + | [single] + when Compare.Int.(String.length single > 0) + && Compare.Char.(single.[0] = '%') -> + parse_field_annot ploc [single] + >>? fun pannot -> ok (p, [], pannot) + | _ -> + ok (p, pannot, None) ) + in + if legacy then + (* legacy semantics ignores spurious annotations *) + let (p, root_name) = + match maybe_root_name with + | Ok (p, _, root_name) -> + (p, root_name) + | Error _ -> + (p, None) + in + ok (p, s, c, root_name) + else + (* only one field annot is allowed to set the root entrypoint name *) + maybe_root_name + >>? fun (p, pannot, root_name) -> + Script_ir_annot.error_unexpected_annot ploc pannot + >>? fun () -> + Script_ir_annot.error_unexpected_annot cloc carrot + >>? fun () -> + Script_ir_annot.error_unexpected_annot sloc sannot + >>? fun () -> ok (p, s, c, root_name) ) + +let parse_code : + ?type_logger:type_logger -> + context -> + legacy:bool -> + code:lazy_expr -> + (ex_code * context) tzresult Lwt.t = + fun ?type_logger ctxt ~legacy ~code -> + Script.force_decode_in_context ctxt code + >>?= fun (code, ctxt) -> + parse_toplevel ~legacy code + >>?= fun (arg_type, storage_type, code_field, root_name) -> + record_trace + (Ill_formed_type (Some "parameter", code, location arg_type)) + (parse_parameter_ty ctxt ~legacy arg_type) + >>?= fun (Ex_ty arg_type, ctxt) -> + (if legacy then ok_unit else well_formed_entrypoints ~root_name arg_type) + >>?= fun () -> + record_trace + (Ill_formed_type (Some "storage", code, location storage_type)) + (parse_storage_ty ctxt ~legacy storage_type) + >>?= fun (Ex_ty storage_type, ctxt) -> + let arg_annot = + default_annot + (type_to_var_annot (name_of_ty arg_type)) + ~default:default_param_annot + in + let storage_annot = + default_annot + (type_to_var_annot (name_of_ty storage_type)) + ~default:default_storage_annot + in + let arg_type_full = + Pair_t + ((arg_type, None, arg_annot), (storage_type, None, storage_annot), None) + in + let ret_type_full = + Pair_t + ( (List_t (Operation_t None, None), None, None), + (storage_type, None, None), + None ) + in + trace + (Ill_typed_contract (code, [])) + (parse_returning + (Toplevel + { + storage_type; + param_type = arg_type; + root_name; + legacy_create_contract_literal = false; + }) + ctxt + ~legacy + ~stack_depth:0 + ?type_logger + (arg_type_full, None) + ret_type_full + code_field) + >|=? fun (code, ctxt) -> + (Ex_code {code; arg_type; storage_type; root_name}, ctxt) + +let parse_storage : + ?type_logger:type_logger -> + context -> + legacy:bool -> + allow_forged:bool -> + 'storage ty -> + storage:lazy_expr -> + ('storage * context) tzresult Lwt.t = + fun ?type_logger ctxt ~legacy ~allow_forged storage_type ~storage -> + Script.force_decode_in_context ctxt storage + >>?= fun (storage, ctxt) -> + trace_eval + (fun () -> + Lwt.return + ( serialize_ty_for_error ctxt storage_type + >|? fun (storage_type, _ctxt) -> + Ill_typed_data (None, storage, storage_type) )) + (parse_data + ?type_logger + ~stack_depth:0 + ctxt + ~legacy + ~allow_forged + storage_type + (root storage)) + +let parse_script : + ?type_logger:type_logger -> + context -> + legacy:bool -> + allow_forged_in_storage:bool -> + Script.t -> + (ex_script * context) tzresult Lwt.t = + fun ?type_logger ctxt ~legacy ~allow_forged_in_storage {code; storage} -> + parse_code ~legacy ctxt ?type_logger ~code + >>=? fun (Ex_code {code; arg_type; storage_type; root_name}, ctxt) -> + parse_storage + ?type_logger + ctxt + ~legacy + ~allow_forged:allow_forged_in_storage + storage_type + ~storage + >|=? fun (storage, ctxt) -> + (Ex_script {code; arg_type; storage; storage_type; root_name}, ctxt) + +let typecheck_code : + legacy:bool -> + context -> + Script.expr -> + (type_map * context) tzresult Lwt.t = + fun ~legacy ctxt code -> + parse_toplevel ~legacy code + >>?= fun (arg_type, storage_type, code_field, root_name) -> + let type_map = ref [] in + record_trace + (Ill_formed_type (Some "parameter", code, location arg_type)) + (parse_parameter_ty ctxt ~legacy arg_type) + >>?= fun (Ex_ty arg_type, ctxt) -> + (if legacy then ok_unit else well_formed_entrypoints ~root_name arg_type) + >>?= fun () -> + record_trace + (Ill_formed_type (Some "storage", code, location storage_type)) + (parse_storage_ty ctxt ~legacy storage_type) + >>?= fun (Ex_ty storage_type, ctxt) -> + let arg_annot = + default_annot + (type_to_var_annot (name_of_ty arg_type)) + ~default:default_param_annot + in + let storage_annot = + default_annot + (type_to_var_annot (name_of_ty storage_type)) + ~default:default_storage_annot + in + let arg_type_full = + Pair_t + ((arg_type, None, arg_annot), (storage_type, None, storage_annot), None) + in + let ret_type_full = + Pair_t + ( (List_t (Operation_t None, None), None, None), + (storage_type, None, None), + None ) + in + let result = + parse_returning + (Toplevel + { + storage_type; + param_type = arg_type; + root_name; + legacy_create_contract_literal = false; + }) + ctxt + ~legacy + ~stack_depth:0 + ~type_logger:(fun loc bef aft -> + type_map := (loc, (bef, aft)) :: !type_map) + (arg_type_full, None) + ret_type_full + code_field + in + trace (Ill_typed_contract (code, !type_map)) result + >|=? fun (Lam _, ctxt) -> (!type_map, ctxt) + +module Entrypoints_map = Map.Make (String) + +let list_entrypoints (type full) (full : full ty) ctxt ~root_name = + let merge path annot (type t) (ty : t ty) reachable + ((unreachables, all) as acc) = + match annot with + | None | Some (Field_annot "") -> ( + ok + @@ + if reachable then acc + else + match ty with + | Union_t _ -> + acc + | _ -> + (List.rev path :: unreachables, all) ) + | Some (Field_annot name) -> + if Compare.Int.(String.length name > 31) then + ok (List.rev path :: unreachables, all) + else if Entrypoints_map.mem name all then + ok (List.rev path :: unreachables, all) + else + unparse_ty ctxt ty + >>? fun (unparsed_ty, _) -> + ok + ( unreachables, + Entrypoints_map.add name (List.rev path, unparsed_ty) all ) + in + let rec fold_tree : + type t. + t ty -> + prim list -> + bool -> + prim list list * (prim list * Script.node) Entrypoints_map.t -> + (prim list list * (prim list * Script.node) Entrypoints_map.t) tzresult = + fun t path reachable acc -> + match t with + | Union_t ((tl, al), (tr, ar), _) -> + merge (D_Left :: path) al tl reachable acc + >>? fun acc -> + merge (D_Right :: path) ar tr reachable acc + >>? fun acc -> + fold_tree + tl + (D_Left :: path) + (match al with Some _ -> true | None -> reachable) + acc + >>? fun acc -> + fold_tree + tr + (D_Right :: path) + (match ar with Some _ -> true | None -> reachable) + acc + | _ -> + ok acc + in + unparse_ty ctxt full + >>? fun (unparsed_full, _) -> + let (init, reachable) = + match root_name with + | None | Some (Field_annot "") -> + (Entrypoints_map.empty, false) + | Some (Field_annot name) -> + (Entrypoints_map.singleton name ([], unparsed_full), true) + in + fold_tree full [] reachable ([], init) + +(* ---- Unparsing (Typed IR -> Untyped expressions) --------------------------*) + +(* -- Unparsing data of any type -- *) + +let comb_witness2 : type t. t ty -> (t, unit -> unit -> unit) comb_witness = + function + | Pair_t (_, (Pair_t _, _, _), _) -> + Comb_Pair (Comb_Pair Comb_Any) + | Pair_t _ -> + Comb_Pair Comb_Any + | _ -> + Comb_Any + +let rec unparse_data : + type a. + context -> + stack_depth:int -> + unparsing_mode -> + a ty -> + a -> + (Script.node * context) tzresult Lwt.t = + fun ctxt ~stack_depth mode ty a -> + Gas.consume ctxt Unparse_costs.unparse_data_cycle + >>?= fun ctxt -> + let non_terminal_recursion ctxt mode ty a = + if Compare.Int.(stack_depth > 10_000) then + fail Unparsing_too_many_recursive_calls + else unparse_data ctxt ~stack_depth:(stack_depth + 1) mode ty a + in + match (ty, a) with + | (Unit_t _, v) -> + Lwt.return @@ unparse_unit ctxt v + | (Int_t _, v) -> + Lwt.return @@ unparse_int ctxt v + | (Nat_t _, v) -> + Lwt.return @@ unparse_nat ctxt v + | (String_t _, s) -> + Lwt.return @@ unparse_string ctxt s + | (Bytes_t _, s) -> + Lwt.return @@ unparse_bytes ctxt s + | (Bool_t _, b) -> + Lwt.return @@ unparse_bool ctxt b + | (Timestamp_t _, t) -> + Lwt.return @@ unparse_timestamp ctxt mode t + | (Address_t _, address) -> + Lwt.return @@ unparse_address ctxt mode address + | (Contract_t _, contract) -> + Lwt.return @@ unparse_contract ctxt mode contract + | (Signature_t _, s) -> + Lwt.return @@ unparse_signature ctxt mode s + | (Mutez_t _, v) -> + Lwt.return @@ unparse_mutez ctxt v + | (Key_t _, k) -> + Lwt.return @@ unparse_key ctxt mode k + | (Key_hash_t _, k) -> + Lwt.return @@ unparse_key_hash ctxt mode k + | (Operation_t _, operation) -> + Lwt.return @@ unparse_operation ctxt operation + | (Chain_id_t _, chain_id) -> + Lwt.return @@ unparse_chain_id ctxt mode chain_id + | (Bls12_381_g1_t _, x) -> + Lwt.return @@ unparse_bls12_381_g1 ctxt x + | (Bls12_381_g2_t _, x) -> + Lwt.return @@ unparse_bls12_381_g2 ctxt x + | (Bls12_381_fr_t _, x) -> + Lwt.return @@ unparse_bls12_381_fr ctxt x + | (Pair_t ((tl, _, _), (tr, _, _), _), pair) -> + let r_witness = comb_witness2 tr in + let unparse_l ctxt v = non_terminal_recursion ctxt mode tl v in + let unparse_r ctxt v = non_terminal_recursion ctxt mode tr v in + unparse_pair unparse_l unparse_r ctxt mode r_witness pair + | (Union_t ((tl, _), (tr, _), _), v) -> + let unparse_l ctxt v = non_terminal_recursion ctxt mode tl v in + let unparse_r ctxt v = non_terminal_recursion ctxt mode tr v in + unparse_union unparse_l unparse_r ctxt v + | (Option_t (t, _), v) -> + let unparse_v ctxt v = non_terminal_recursion ctxt mode t v in + unparse_option unparse_v ctxt v + | (List_t (t, _), items) -> + fold_left_s + (fun (l, ctxt) element -> + non_terminal_recursion ctxt mode t element + >|=? fun (unparsed, ctxt) -> (unparsed :: l, ctxt)) + ([], ctxt) + items.elements + >|=? fun (items, ctxt) -> (Micheline.Seq (-1, List.rev items), ctxt) + | (Ticket_t (t, _), {ticketer; contents; amount}) -> + let t = ty_of_comparable_ty @@ opened_ticket_type t in + unparse_data ctxt ~stack_depth mode t (ticketer, (contents, amount)) + | (Set_t (t, _), set) -> + fold_left_s + (fun (l, ctxt) item -> + unparse_comparable_data ctxt mode t item + >|=? fun (item, ctxt) -> (item :: l, ctxt)) + ([], ctxt) + (set_fold (fun e acc -> e :: acc) set []) + >|=? fun (items, ctxt) -> (Micheline.Seq (-1, items), ctxt) + | (Map_t (kt, vt, _), map) -> + let items = map_fold (fun k v acc -> (k, v) :: acc) map [] in + unparse_items ctxt ~stack_depth:(stack_depth + 1) mode kt vt items + >|=? fun (items, ctxt) -> (Micheline.Seq (-1, items), ctxt) + | (Big_map_t (_kt, _vt, _), {id = Some id; diff = {size}; _}) + when Compare.Int.( = ) size 0 -> + return (Micheline.Int (-1, Big_map.Id.unparse_to_z id), ctxt) + | (Big_map_t (kt, vt, _), {id = Some id; diff = {map; _}; _}) -> + let items = + Big_map_overlay.fold (fun _ (k, v) acc -> (k, v) :: acc) map [] + in + let items = + (* Sort the items in Michelson comparison order and not in key + hash order. This code path is only exercized for tracing, + so we don't bother carbonating this sort operation + precisely. Also, the sort uses a reverse compare because + [unparse_items] will reverse the result. *) + List.sort (fun (a, _) (b, _) -> compare_comparable kt b a) items + in + let vt = Option_t (vt, None) in + unparse_items ctxt ~stack_depth:(stack_depth + 1) mode kt vt items + >|=? fun (items, ctxt) -> + ( Micheline.Prim + ( -1, + D_Pair, + [Int (-1, Big_map.Id.unparse_to_z id); Seq (-1, items)], + [] ), + ctxt ) + | (Big_map_t (kt, vt, _), {id = None; diff = {map; _}; _}) -> + let items = + Big_map_overlay.fold + (fun _ (k, v) acc -> + match v with None -> acc | Some v -> (k, v) :: acc) + map + [] + in + let items = + (* See note above. *) + List.sort (fun (a, _) (b, _) -> compare_comparable kt b a) items + in + unparse_items ctxt ~stack_depth:(stack_depth + 1) mode kt vt items + >|=? fun (items, ctxt) -> (Micheline.Seq (-1, items), ctxt) + | (Lambda_t _, Lam (_, original_code)) -> + unparse_code ctxt ~stack_depth:(stack_depth + 1) mode original_code + | (Never_t _, _) -> + . + | (Sapling_transaction_t _, s) -> + Lwt.return + ( Gas.consume ctxt (Unparse_costs.sapling_transaction s) + >|? fun ctxt -> + let bytes = + Data_encoding.Binary.to_bytes_exn Sapling.transaction_encoding s + in + (Bytes (-1, bytes), ctxt) ) + | (Sapling_state_t _, {id; diff; _}) -> + Lwt.return + ( Gas.consume ctxt (Unparse_costs.sapling_diff diff) + >|? fun ctxt -> + ( ( match diff with + | {commitments_and_ciphertexts = []; nullifiers = []} -> ( + match id with + | None -> + Micheline.Seq (-1, []) + | Some id -> + let id = Sapling.Id.unparse_to_z id in + Micheline.Int (-1, id) ) + | diff -> ( + let diff_bytes = + Data_encoding.Binary.to_bytes_exn Sapling.diff_encoding diff + in + let unparsed_diff = Bytes (-1, diff_bytes) in + match id with + | None -> + unparsed_diff + | Some id -> + let id = Sapling.Id.unparse_to_z id in + Micheline.Prim (-1, D_Pair, [Int (-1, id); unparsed_diff], []) + ) ), + ctxt ) ) + +and unparse_items : + type k v. + context -> + stack_depth:int -> + unparsing_mode -> + k comparable_ty -> + v ty -> + (k * v) list -> + (Script.node list * context) tzresult Lwt.t = + fun ctxt ~stack_depth mode kt vt items -> + fold_left_s + (fun (l, ctxt) (k, v) -> + unparse_comparable_data ctxt mode kt k + >>=? fun (key, ctxt) -> + unparse_data ctxt ~stack_depth:(stack_depth + 1) mode vt v + >|=? fun (value, ctxt) -> (Prim (-1, D_Elt, [key; value], []) :: l, ctxt)) + ([], ctxt) + items + +and unparse_code ctxt ~stack_depth mode code = + let legacy = true in + Gas.consume ctxt Unparse_costs.unparse_instr_cycle + >>?= fun ctxt -> + let non_terminal_recursion ctxt mode code = + if Compare.Int.(stack_depth > 10_000) then + fail Unparsing_too_many_recursive_calls + else unparse_code ctxt ~stack_depth:(stack_depth + 1) mode code + in + match code with + | Prim (loc, I_PUSH, [ty; data], annot) -> + parse_packable_ty ctxt ~legacy ty + >>?= fun (Ex_ty t, ctxt) -> + let allow_forged = + false + (* Forgeable in PUSH data are already forbidden at parsing, + the only case for which this matters is storing a lambda resulting + from APPLYing a non-forgeable but this cannot happen either as long + as all packable values are also forgeable. *) + in + parse_data + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + ~allow_forged + t + data + >>=? fun (data, ctxt) -> + unparse_data ctxt ~stack_depth:(stack_depth + 1) mode t data + >>=? fun (data, ctxt) -> + return (Prim (loc, I_PUSH, [ty; data], annot), ctxt) + | Seq (loc, items) -> + fold_left_s + (fun (l, ctxt) item -> + non_terminal_recursion ctxt mode item + >|=? fun (item, ctxt) -> (item :: l, ctxt)) + ([], ctxt) + items + >>=? fun (items, ctxt) -> + return (Micheline.Seq (loc, List.rev items), ctxt) + | Prim (loc, prim, items, annot) -> + fold_left_s + (fun (l, ctxt) item -> + non_terminal_recursion ctxt mode item + >|=? fun (item, ctxt) -> (item :: l, ctxt)) + ([], ctxt) + items + >>=? fun (items, ctxt) -> + return (Prim (loc, prim, List.rev items, annot), ctxt) + | (Int _ | String _ | Bytes _) as atom -> + return (atom, ctxt) + +(* Gas accounting may not be perfect in this function, as it is only called by RPCs. *) +let unparse_script ctxt mode {code; arg_type; storage; storage_type; root_name} + = + let (Lam (_, original_code)) = code in + unparse_code ctxt ~stack_depth:0 mode original_code + >>=? fun (code, ctxt) -> + unparse_data ctxt ~stack_depth:0 mode storage_type storage + >>=? fun (storage, ctxt) -> + Lwt.return + ( unparse_ty ctxt arg_type + >>? fun (arg_type, ctxt) -> + unparse_ty ctxt storage_type + >>? fun (storage_type, ctxt) -> + let arg_type = add_field_annot root_name None arg_type in + let open Micheline in + let code = + Seq + ( -1, + [ Prim (-1, K_parameter, [arg_type], []); + Prim (-1, K_storage, [storage_type], []); + Prim (-1, K_code, [code], []) ] ) + in + Gas.consume ctxt Unparse_costs.unparse_instr_cycle + >>? fun ctxt -> + Gas.consume ctxt Unparse_costs.unparse_instr_cycle + >>? fun ctxt -> + Gas.consume ctxt Unparse_costs.unparse_instr_cycle + >>? fun ctxt -> + Gas.consume ctxt Unparse_costs.unparse_instr_cycle + >>? fun ctxt -> + Gas.consume ctxt (Script.strip_locations_cost code) + >>? fun ctxt -> + Gas.consume ctxt (Script.strip_locations_cost storage) + >|? fun ctxt -> + ( { + code = lazy_expr (strip_locations code); + storage = lazy_expr (strip_locations storage); + }, + ctxt ) ) + +let pack_data ctxt typ data ~mode = + unparse_data ~stack_depth:0 ctxt mode typ data + >>=? fun (unparsed, ctxt) -> Lwt.return @@ pack_node unparsed ctxt + +let hash_data ctxt typ data = + pack_data ctxt typ data ~mode:Optimized_legacy + >>=? fun (bytes, ctxt) -> Lwt.return @@ hash_bytes ctxt bytes + +let pack_data ctxt typ data = pack_data ctxt typ data ~mode:Optimized_legacy + +(* ---------------- Big map -------------------------------------------------*) + +let empty_big_map key_type value_type = + { + id = None; + diff = {map = Big_map_overlay.empty; size = 0}; + key_type; + value_type; + } + +let big_map_mem ctxt key {id; diff; key_type; _} = + hash_comparable_data ctxt key_type key + >>=? fun (key, ctxt) -> + match (Big_map_overlay.find_opt key diff.map, id) with + | (None, None) -> + return (false, ctxt) + | (None, Some id) -> + Alpha_context.Big_map.mem ctxt id key >|=? fun (ctxt, res) -> (res, ctxt) + | (Some (_, None), _) -> + return (false, ctxt) + | (Some (_, Some _), _) -> + return (true, ctxt) + +let big_map_get_by_hash ctxt key {id; diff; value_type} = + match (Big_map_overlay.find_opt key diff.map, id) with + | (Some (_, x), _) -> + return (x, ctxt) + | (None, None) -> + return (None, ctxt) + | (None, Some id) -> ( + Alpha_context.Big_map.get_opt ctxt id key + >>=? function + | (ctxt, None) -> + return (None, ctxt) + | (ctxt, Some value) -> + parse_data + ~stack_depth:0 + ctxt + ~legacy:true + ~allow_forged:true + value_type + (Micheline.root value) + >|=? fun (x, ctxt) -> (Some x, ctxt) ) + +let big_map_get ctxt key map = + hash_comparable_data ctxt map.key_type key + >>=? fun (key_hash, ctxt) -> big_map_get_by_hash ctxt key_hash map + +let big_map_update_by_hash ctxt key_hash key value map = + let contains = Big_map_overlay.mem key_hash map.diff.map in + return + ( { + map with + diff = + { + map = Big_map_overlay.add key_hash (key, value) map.diff.map; + size = (if contains then map.diff.size else map.diff.size + 1); + }; + }, + ctxt ) + +let big_map_update ctxt key value map = + hash_comparable_data ctxt map.key_type key + >>=? fun (key_hash, ctxt) -> + big_map_update_by_hash ctxt key_hash key value map + +let big_map_get_and_update ctxt key value map = + hash_comparable_data ctxt map.key_type key + >>=? fun (key_hash, ctxt) -> + big_map_update_by_hash ctxt key_hash key value map + >>=? fun (map', ctxt) -> + big_map_get_by_hash ctxt key_hash map + >>=? fun (old_value, ctxt) -> return (old_value, map', ctxt) + +(* ---------------- Lazy storage---------------------------------------------*) + +type lazy_storage_ids = Lazy_storage.IdSet.t + +let no_lazy_storage_id = Lazy_storage.IdSet.empty + +let diff_of_big_map ctxt mode ~temporary ~ids_to_copy + {id; key_type; value_type; diff} = + ( match id with + | Some id -> + if Lazy_storage.IdSet.mem Big_map id ids_to_copy then + Big_map.fresh ~temporary ctxt + >|=? fun (ctxt, duplicate) -> + (ctxt, Lazy_storage.Copy {src = id}, duplicate) + else + (* The first occurrence encountered of a big_map reuses the + ID. This way, the payer is only charged for the diff. + For this to work, this diff has to be put at the end of + the global diff, otherwise the duplicates will use the + updated version as a base. This is true because we add + this diff first in the accumulator of + `extract_lazy_storage_updates`, and this accumulator is not + reversed. *) + return (ctxt, Lazy_storage.Existing, id) + | None -> + Big_map.fresh ~temporary ctxt + >>=? fun (ctxt, id) -> + Lwt.return + (let kt = unparse_comparable_ty key_type in + Gas.consume ctxt (Script.strip_locations_cost kt) + >>? fun ctxt -> + unparse_ty ctxt value_type + >>? fun (kv, ctxt) -> + Gas.consume ctxt (Script.strip_locations_cost kv) + >|? fun ctxt -> + let key_type = Micheline.strip_locations kt in + let value_type = Micheline.strip_locations kv in + (ctxt, Lazy_storage.(Alloc Big_map.{key_type; value_type}), id)) ) + >>=? fun (ctxt, init, id) -> + let pairs = + Big_map_overlay.fold + (fun key_hash (key, value) acc -> (key_hash, key, value) :: acc) + diff.map + [] + in + fold_left_s + (fun (acc, ctxt) (key_hash, key, value) -> + Gas.consume ctxt Typecheck_costs.parse_instr_cycle + >>?= fun ctxt -> + unparse_comparable_data ctxt mode key_type key + >>=? fun (key_node, ctxt) -> + Gas.consume ctxt (Script.strip_locations_cost key_node) + >>?= fun ctxt -> + let key = Micheline.strip_locations key_node in + ( match value with + | None -> + return (None, ctxt) + | Some x -> + unparse_data ~stack_depth:0 ctxt mode value_type x + >>=? fun (node, ctxt) -> + Lwt.return + ( Gas.consume ctxt (Script.strip_locations_cost node) + >|? fun ctxt -> (Some (Micheline.strip_locations node), ctxt) ) ) + >|=? fun (value, ctxt) -> + let diff_item = Big_map.{key; key_hash; value} in + (diff_item :: acc, ctxt)) + ([], ctxt) + (List.rev pairs) + >|=? fun (updates, ctxt) -> (Lazy_storage.Update {init; updates}, id, ctxt) + +let diff_of_sapling_state ctxt ~temporary ~ids_to_copy + ({id; diff; memo_size} : Sapling.state) = + ( match id with + | Some id -> + if Lazy_storage.IdSet.mem Sapling_state id ids_to_copy then + Sapling.fresh ~temporary ctxt + >|=? fun (ctxt, duplicate) -> + (ctxt, Lazy_storage.Copy {src = id}, duplicate) + else return (ctxt, Lazy_storage.Existing, id) + | None -> + Sapling.fresh ~temporary ctxt + >|=? fun (ctxt, id) -> (ctxt, Lazy_storage.Alloc Sapling.{memo_size}, id) + ) + >|=? fun (ctxt, init, id) -> + (Lazy_storage.Update {init; updates = diff}, id, ctxt) + +(** + Witness flag for whether a type can be populated by a value containing a + lazy storage. + [False_f] must be used only when a value of the type cannot contain a lazy + storage. + + This flag is built in [has_lazy_storage] and used only in + [extract_lazy_storage_updates] and [collect_lazy_storage]. + + This flag is necessary to avoid these two functions to have a quadratic + complexity in the size of the type. + + Add new lazy storage kinds here. + + Please keep the usage of this GADT local. +*) +type 'ty has_lazy_storage = + | True_f : _ has_lazy_storage + | False_f : _ has_lazy_storage + | Pair_f : + 'a has_lazy_storage * 'b has_lazy_storage + -> ('a, 'b) pair has_lazy_storage + | Union_f : + 'a has_lazy_storage * 'b has_lazy_storage + -> ('a, 'b) union has_lazy_storage + | Option_f : 'a has_lazy_storage -> 'a option has_lazy_storage + | List_f : 'a has_lazy_storage -> 'a boxed_list has_lazy_storage + | Map_f : 'v has_lazy_storage -> (_, 'v) map has_lazy_storage + +(** + This function is called only on storage and parameter types of contracts, + once per typechecked contract. It has a complexity linear in the size of + the types, which happen to be literally written types, so the gas for them + has already been paid. +*) +let rec has_lazy_storage : type t. t ty -> t has_lazy_storage = + let aux1 cons t = + match has_lazy_storage t with False_f -> False_f | h -> cons h + in + let aux2 cons t1 t2 = + match (has_lazy_storage t1, has_lazy_storage t2) with + | (False_f, False_f) -> + False_f + | (h1, h2) -> + cons h1 h2 + in + function + | Big_map_t (_, _, _) -> + True_f + | Sapling_state_t _ -> + True_f + | Unit_t _ -> + False_f + | Int_t _ -> + False_f + | Nat_t _ -> + False_f + | Signature_t _ -> + False_f + | String_t _ -> + False_f + | Bytes_t _ -> + False_f + | Mutez_t _ -> + False_f + | Key_hash_t _ -> + False_f + | Key_t _ -> + False_f + | Timestamp_t _ -> + False_f + | Address_t _ -> + False_f + | Bool_t _ -> + False_f + | Lambda_t (_, _, _) -> + False_f + | Set_t (_, _) -> + False_f + | Contract_t (_, _) -> + False_f + | Operation_t _ -> + False_f + | Chain_id_t _ -> + False_f + | Never_t _ -> + False_f + | Bls12_381_g1_t _ -> + False_f + | Bls12_381_g2_t _ -> + False_f + | Bls12_381_fr_t _ -> + False_f + | Sapling_transaction_t _ -> + False_f + | Ticket_t _ -> + False_f + | Pair_t ((l, _, _), (r, _, _), _) -> + aux2 (fun l r -> Pair_f (l, r)) l r + | Union_t ((l, _), (r, _), _) -> + aux2 (fun l r -> Union_f (l, r)) l r + | Option_t (t, _) -> + aux1 (fun h -> Option_f h) t + | List_t (t, _) -> + aux1 (fun h -> List_f h) t + | Map_t (_, t, _) -> + aux1 (fun h -> Map_f h) t + +(** + Transforms a value potentially containing lazy storage in an intermediary + state to a value containing lazy storage only represented by identifiers. + + Returns the updated value, the updated set of ids to copy, and the lazy + storage diff to show on the receipt and apply on the storage. +*) +let extract_lazy_storage_updates ctxt mode ~temporary ids_to_copy acc ty x = + let rec aux : + type a. + context -> + unparsing_mode -> + temporary:bool -> + Lazy_storage.IdSet.t -> + Lazy_storage.diffs -> + a ty -> + a -> + has_lazy_storage:a has_lazy_storage -> + (context * a * Lazy_storage.IdSet.t * Lazy_storage.diffs) tzresult Lwt.t + = + fun ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage -> + Gas.consume ctxt Typecheck_costs.parse_instr_cycle + >>?= fun ctxt -> + match (has_lazy_storage, ty, x) with + | (False_f, _, _) -> + return (ctxt, x, ids_to_copy, acc) + | (_, Big_map_t (_, _, _), map) -> + diff_of_big_map ctxt mode ~temporary ~ids_to_copy map + >|=? fun (diff, id, ctxt) -> + let map = + { + map with + diff = {map = Big_map_overlay.empty; size = 0}; + id = Some id; + } + in + let diff = Lazy_storage.make Big_map id diff in + let ids_to_copy = Lazy_storage.IdSet.add Big_map id ids_to_copy in + (ctxt, map, ids_to_copy, diff :: acc) + | (_, Sapling_state_t _, sapling_state) -> + diff_of_sapling_state ctxt ~temporary ~ids_to_copy sapling_state + >|=? fun (diff, id, ctxt) -> + let sapling_state = + Sapling.empty_state ~id ~memo_size:sapling_state.memo_size () + in + let diff = Lazy_storage.make Sapling_state id diff in + let ids_to_copy = + Lazy_storage.IdSet.add Sapling_state id ids_to_copy + in + (ctxt, sapling_state, ids_to_copy, diff :: acc) + | (Pair_f (hl, hr), Pair_t ((tyl, _, _), (tyr, _, _), _), (xl, xr)) -> + aux ctxt mode ~temporary ids_to_copy acc tyl xl ~has_lazy_storage:hl + >>=? fun (ctxt, xl, ids_to_copy, acc) -> + aux ctxt mode ~temporary ids_to_copy acc tyr xr ~has_lazy_storage:hr + >|=? fun (ctxt, xr, ids_to_copy, acc) -> + (ctxt, (xl, xr), ids_to_copy, acc) + | (Union_f (has_lazy_storage, _), Union_t ((ty, _), (_, _), _), L x) -> + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + >|=? fun (ctxt, x, ids_to_copy, acc) -> (ctxt, L x, ids_to_copy, acc) + | (Union_f (_, has_lazy_storage), Union_t ((_, _), (ty, _), _), R x) -> + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + >|=? fun (ctxt, x, ids_to_copy, acc) -> (ctxt, R x, ids_to_copy, acc) + | (Option_f has_lazy_storage, Option_t (ty, _), Some x) -> + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + >|=? fun (ctxt, x, ids_to_copy, acc) -> (ctxt, Some x, ids_to_copy, acc) + | (List_f has_lazy_storage, List_t (ty, _), l) -> + fold_left_s + (fun (ctxt, l, ids_to_copy, acc) x -> + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + >|=? fun (ctxt, x, ids_to_copy, acc) -> + (ctxt, list_cons x l, ids_to_copy, acc)) + (ctxt, list_empty, ids_to_copy, acc) + l.elements + >|=? fun (ctxt, l, ids_to_copy, acc) -> + let reversed = {length = l.length; elements = List.rev l.elements} in + (ctxt, reversed, ids_to_copy, acc) + | (Map_f has_lazy_storage, Map_t (_, ty, _), (module M)) -> + fold_left_s + (fun (ctxt, m, ids_to_copy, acc) (k, x) -> + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + >|=? fun (ctxt, x, ids_to_copy, acc) -> + (ctxt, M.OPS.add k x m, ids_to_copy, acc)) + (ctxt, M.OPS.empty, ids_to_copy, acc) + (M.OPS.bindings (fst M.boxed)) + >|=? fun (ctxt, m, ids_to_copy, acc) -> + let module M = struct + module OPS = M.OPS + + type key = M.key + + type value = M.value + + let key_ty = M.key_ty + + let boxed = (m, snd M.boxed) + end in + ( ctxt, + (module M : Boxed_map with type key = M.key and type value = M.value), + ids_to_copy, + acc ) + | (_, Option_t (_, _), None) -> + return (ctxt, None, ids_to_copy, acc) + | _ -> + assert false + (* TODO: fix injectivity of types *) + in + let has_lazy_storage = has_lazy_storage ty in + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + +let rec fold_lazy_storage : + type a. + f:'acc Lazy_storage.IdSet.fold_f -> + init:'acc -> + context -> + a ty -> + a -> + has_lazy_storage:a has_lazy_storage -> + ('acc * context) tzresult = + fun ~f ~init ctxt ty x ~has_lazy_storage -> + Gas.consume ctxt Typecheck_costs.parse_instr_cycle + >>? fun ctxt -> + match (has_lazy_storage, ty, x) with + | (_, Big_map_t (_, _, _), {id = Some id}) -> + Gas.consume ctxt Typecheck_costs.parse_instr_cycle + >>? fun ctxt -> ok (f.f Big_map id init, ctxt) + | (_, Sapling_state_t _, {id = Some id}) -> + Gas.consume ctxt Typecheck_costs.parse_instr_cycle + >>? fun ctxt -> ok (f.f Sapling_state id init, ctxt) + | (False_f, _, _) -> + ok (init, ctxt) + | (_, Big_map_t (_, _, _), {id = None}) -> + ok (init, ctxt) + | (_, Sapling_state_t _, {id = None}) -> + ok (init, ctxt) + | (Pair_f (hl, hr), Pair_t ((tyl, _, _), (tyr, _, _), _), (xl, xr)) -> + fold_lazy_storage ~f ~init ctxt tyl xl ~has_lazy_storage:hl + >>? fun (init, ctxt) -> + fold_lazy_storage ~f ~init ctxt tyr xr ~has_lazy_storage:hr + | (Union_f (has_lazy_storage, _), Union_t ((ty, _), (_, _), _), L x) -> + fold_lazy_storage ~f ~init ctxt ty x ~has_lazy_storage + | (Union_f (_, has_lazy_storage), Union_t ((_, _), (ty, _), _), R x) -> + fold_lazy_storage ~f ~init ctxt ty x ~has_lazy_storage + | (_, Option_t (_, _), None) -> + ok (init, ctxt) + | (Option_f has_lazy_storage, Option_t (ty, _), Some x) -> + fold_lazy_storage ~f ~init ctxt ty x ~has_lazy_storage + | (List_f has_lazy_storage, List_t (ty, _), l) -> + List.fold_left + (fun acc x -> + acc + >>? fun (init, ctxt) -> + fold_lazy_storage ~f ~init ctxt ty x ~has_lazy_storage) + (ok (init, ctxt)) + l.elements + | (Map_f has_lazy_storage, Map_t (_, ty, _), m) -> + map_fold + (fun _ v acc -> + acc + >>? fun (init, ctxt) -> + fold_lazy_storage ~f ~init ctxt ty v ~has_lazy_storage) + m + (ok (init, ctxt)) + | _ -> + (* TODO: fix injectivity of types *) assert false + +let collect_lazy_storage ctxt ty x = + let has_lazy_storage = has_lazy_storage ty in + fold_lazy_storage + ~f:{f = (fun kind id acc -> Lazy_storage.IdSet.add kind id acc)} + ~init:no_lazy_storage_id + ctxt + ty + x + ~has_lazy_storage + +let extract_lazy_storage_diff ctxt mode ~temporary ~to_duplicate ~to_update ty + v = + (* + Basically [to_duplicate] are ids from the argument and [to_update] are ids + from the storage before execution (i.e. it is safe to reuse them since they + will be owned by the same contract). + *) + let to_duplicate = Lazy_storage.IdSet.diff to_duplicate to_update in + extract_lazy_storage_updates ctxt mode ~temporary to_duplicate [] ty v + >|=? fun (ctxt, v, alive, diffs) -> + let diffs = + if temporary then diffs + else + let dead = Lazy_storage.IdSet.diff to_update alive in + Lazy_storage.IdSet.fold_all + {f = (fun kind id acc -> Lazy_storage.make kind id Remove :: acc)} + dead + diffs + in + match diffs with + | [] -> + (v, None, ctxt) + | diffs -> + (v, Some diffs (* do not reverse *), ctxt) + +let list_of_big_map_ids ids = + Lazy_storage.IdSet.fold Big_map (fun id acc -> id :: acc) ids [] + +let parse_data = parse_data ~stack_depth:0 + +let parse_instr = parse_instr ~stack_depth:0 + +let unparse_data = unparse_data ~stack_depth:0 + +let unparse_code = unparse_code ~stack_depth:0 + +let get_single_sapling_state ctxt ty x = + let has_lazy_storage = has_lazy_storage ty in + let f (type i a u) (kind : (i, a, u) Lazy_storage.Kind.t) (id : i) + single_id_opt : Sapling.Id.t option = + match kind with + | Lazy_storage.Kind.Sapling_state -> ( + match single_id_opt with None -> Some id | Some _ -> raise Not_found + (* more than one *) ) + | _ -> + single_id_opt + in + fold_lazy_storage ~f:{f} ~init:None ctxt ty x ~has_lazy_storage + >>? function (None, _) -> raise Not_found | (Some id, ctxt) -> ok (id, ctxt) diff --git a/src/proto_009_PsFLoren/lib_protocol/script_ir_translator.mli b/src/proto_009_PsFLoren/lib_protocol/script_ir_translator.mli new file mode 100644 index 0000000000000000000000000000000000000000..8cfcbff2b29b0c7418b4d0cb0c27eab79e936057 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_ir_translator.mli @@ -0,0 +1,365 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script_tc_errors + +type ('ta, 'tb) eq = Eq : ('same, 'same) eq + +type ex_comparable_ty = + | Ex_comparable_ty : 'a Script_typed_ir.comparable_ty -> ex_comparable_ty + +type ex_ty = Ex_ty : 'a Script_typed_ir.ty -> ex_ty + +type ex_stack_ty = Ex_stack_ty : 'a Script_typed_ir.stack_ty -> ex_stack_ty + +type ex_script = Ex_script : ('a, 'b) Script_typed_ir.script -> ex_script + +type ('arg, 'storage) code = { + code : + ( ('arg, 'storage) Script_typed_ir.pair, + ( Script_typed_ir.operation Script_typed_ir.boxed_list, + 'storage ) + Script_typed_ir.pair ) + Script_typed_ir.lambda; + arg_type : 'arg Script_typed_ir.ty; + storage_type : 'storage Script_typed_ir.ty; + root_name : Script_typed_ir.field_annot option; +} + +type ex_code = Ex_code : ('a, 'c) code -> ex_code + +type tc_context = + | Lambda : tc_context + | Dip : 'a Script_typed_ir.stack_ty * tc_context -> tc_context + | Toplevel : { + storage_type : 'sto Script_typed_ir.ty; + param_type : 'param Script_typed_ir.ty; + root_name : Script_typed_ir.field_annot option; + legacy_create_contract_literal : bool; + } + -> tc_context + +type 'bef judgement = + | Typed : ('bef, 'aft) Script_typed_ir.descr -> 'bef judgement + | Failed : { + descr : + 'aft. 'aft Script_typed_ir.stack_ty -> + ('bef, 'aft) Script_typed_ir.descr; + } + -> 'bef judgement + +type unparsing_mode = Optimized | Readable | Optimized_legacy + +type type_logger = + int -> + (Script.expr * Script.annot) list -> + (Script.expr * Script.annot) list -> + unit + +(* ---- Lists, Sets and Maps ----------------------------------------------- *) + +val list_empty : 'a Script_typed_ir.boxed_list + +val list_cons : + 'a -> 'a Script_typed_ir.boxed_list -> 'a Script_typed_ir.boxed_list + +val empty_set : 'a Script_typed_ir.comparable_ty -> 'a Script_typed_ir.set + +val set_fold : + ('elt -> 'acc -> 'acc) -> 'elt Script_typed_ir.set -> 'acc -> 'acc + +val set_update : 'a -> bool -> 'a Script_typed_ir.set -> 'a Script_typed_ir.set + +val set_mem : 'elt -> 'elt Script_typed_ir.set -> bool + +val set_size : 'elt Script_typed_ir.set -> Script_int.n Script_int.num + +val empty_map : + 'a Script_typed_ir.comparable_ty -> ('a, 'b) Script_typed_ir.map + +val map_fold : + ('key -> 'value -> 'acc -> 'acc) -> + ('key, 'value) Script_typed_ir.map -> + 'acc -> + 'acc + +val map_update : + 'a -> + 'b option -> + ('a, 'b) Script_typed_ir.map -> + ('a, 'b) Script_typed_ir.map + +val map_mem : 'key -> ('key, 'value) Script_typed_ir.map -> bool + +val map_get : 'key -> ('key, 'value) Script_typed_ir.map -> 'value option + +val map_key_ty : + ('a, 'b) Script_typed_ir.map -> 'a Script_typed_ir.comparable_ty + +val map_size : ('a, 'b) Script_typed_ir.map -> Script_int.n Script_int.num + +val empty_big_map : + 'a Script_typed_ir.comparable_ty -> + 'b Script_typed_ir.ty -> + ('a, 'b) Script_typed_ir.big_map + +val big_map_mem : + context -> + 'key -> + ('key, 'value) Script_typed_ir.big_map -> + (bool * context) tzresult Lwt.t + +val big_map_get : + context -> + 'key -> + ('key, 'value) Script_typed_ir.big_map -> + ('value option * context) tzresult Lwt.t + +val big_map_update : + context -> + 'key -> + 'value option -> + ('key, 'value) Script_typed_ir.big_map -> + (('key, 'value) Script_typed_ir.big_map * context) tzresult Lwt.t + +val big_map_get_and_update : + context -> + 'key -> + 'value option -> + ('key, 'value) Script_typed_ir.big_map -> + ('value option * ('key, 'value) Script_typed_ir.big_map * context) tzresult + Lwt.t + +val ty_eq : + context -> + Script.location -> + 'ta Script_typed_ir.ty -> + 'tb Script_typed_ir.ty -> + (('ta Script_typed_ir.ty, 'tb Script_typed_ir.ty) eq * context) tzresult + +val compare_address : Script_typed_ir.address -> Script_typed_ir.address -> int + +val compare_comparable : 'a Script_typed_ir.comparable_ty -> 'a -> 'a -> int + +val parse_comparable_data : + ?type_logger:type_logger -> + context -> + 'a Script_typed_ir.comparable_ty -> + Script.node -> + ('a * context) tzresult Lwt.t + +val parse_data : + ?type_logger:type_logger -> + context -> + legacy:bool -> + allow_forged:bool -> + 'a Script_typed_ir.ty -> + Script.node -> + ('a * context) tzresult Lwt.t + +val unparse_data : + context -> + unparsing_mode -> + 'a Script_typed_ir.ty -> + 'a -> + (Script.node * context) tzresult Lwt.t + +val unparse_code : + context -> + unparsing_mode -> + Script.node -> + (Script.node * context) tzresult Lwt.t + +val parse_instr : + ?type_logger:type_logger -> + tc_context -> + context -> + legacy:bool -> + Script.node -> + 'bef Script_typed_ir.stack_ty -> + ('bef judgement * context) tzresult Lwt.t + +(** + [parse_ty] specialized for the right-hand side part of a big map type, i.e. + the `value` in `big_map key value`. +*) +val parse_big_map_value_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult + +val parse_packable_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult + +val parse_parameter_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult + +val parse_comparable_ty : + context -> Script.node -> (ex_comparable_ty * context) tzresult + +(** + [parse_ty] allowing big_map values, operations, contract and tickets. +*) +val parse_any_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult + +(** We expose [parse_ty] for convenience to external tools. Please use + specialized versions such as [parse_packable_ty], [parse_parameter_ty], + [parse_comparable_ty], or [parse_big_map_value_ty] if possible. *) +val parse_ty : + context -> + legacy:bool -> + allow_lazy_storage:bool -> + allow_operation:bool -> + allow_contract:bool -> + allow_ticket:bool -> + Script.node -> + (ex_ty * context) tzresult + +val unparse_ty : + context -> 'a Script_typed_ir.ty -> (Script.node * context) tzresult + +val parse_toplevel : + legacy:bool -> + Script.expr -> + (Script.node * Script.node * Script.node * Script_typed_ir.field_annot option) + tzresult + +val add_field_annot : + Script_typed_ir.field_annot option -> + Script_typed_ir.var_annot option -> + Script.node -> + Script.node + +val typecheck_code : + legacy:bool -> context -> Script.expr -> (type_map * context) tzresult Lwt.t + +val serialize_ty_for_error : + context -> 'a Script_typed_ir.ty -> (Script.expr * context) tzresult + +val parse_code : + ?type_logger:type_logger -> + context -> + legacy:bool -> + code:Script.lazy_expr -> + (ex_code * context) tzresult Lwt.t + +val parse_storage : + ?type_logger:type_logger -> + context -> + legacy:bool -> + allow_forged:bool -> + 'storage Script_typed_ir.ty -> + storage:Script.lazy_expr -> + ('storage * context) tzresult Lwt.t + +(** Combines [parse_code] and [parse_storage] *) +val parse_script : + ?type_logger:type_logger -> + context -> + legacy:bool -> + allow_forged_in_storage:bool -> + Script.t -> + (ex_script * context) tzresult Lwt.t + +(* Gas accounting may not be perfect in this function, as it is only called by RPCs. *) +val unparse_script : + context -> + unparsing_mode -> + ('a, 'b) Script_typed_ir.script -> + (Script.t * context) tzresult Lwt.t + +val parse_contract : + legacy:bool -> + context -> + Script.location -> + 'a Script_typed_ir.ty -> + Contract.t -> + entrypoint:string -> + (context * 'a Script_typed_ir.typed_contract) tzresult Lwt.t + +val parse_contract_for_script : + context -> + Script.location -> + 'a Script_typed_ir.ty -> + Contract.t -> + entrypoint:string -> + (context * 'a Script_typed_ir.typed_contract option) tzresult Lwt.t + +val find_entrypoint : + 't Script_typed_ir.ty -> + root_name:Script_typed_ir.field_annot option -> + string -> + ((Script.node -> Script.node) * ex_ty) tzresult + +module Entrypoints_map : S.MAP with type key = string + +val list_entrypoints : + 't Script_typed_ir.ty -> + context -> + root_name:Script_typed_ir.field_annot option -> + ( Michelson_v1_primitives.prim list list + * (Michelson_v1_primitives.prim list * Script.node) Entrypoints_map.t ) + tzresult + +val pack_data : + context -> 'a Script_typed_ir.ty -> 'a -> (bytes * context) tzresult Lwt.t + +val hash_comparable_data : + context -> + 'a Script_typed_ir.comparable_ty -> + 'a -> + (Script_expr_hash.t * context) tzresult Lwt.t + +val hash_data : + context -> + 'a Script_typed_ir.ty -> + 'a -> + (Script_expr_hash.t * context) tzresult Lwt.t + +type lazy_storage_ids + +val no_lazy_storage_id : lazy_storage_ids + +val collect_lazy_storage : + context -> + 'a Script_typed_ir.ty -> + 'a -> + (lazy_storage_ids * context) tzresult + +val list_of_big_map_ids : lazy_storage_ids -> Big_map.Id.t list + +val extract_lazy_storage_diff : + context -> + unparsing_mode -> + temporary:bool -> + to_duplicate:lazy_storage_ids -> + to_update:lazy_storage_ids -> + 'a Script_typed_ir.ty -> + 'a -> + ('a * Lazy_storage.diffs option * context) tzresult Lwt.t + +(* raise Not_found if none or more than one found *) +val get_single_sapling_state : + context -> 'a Script_typed_ir.ty -> 'a -> (Sapling.Id.t * context) tzresult diff --git a/src/proto_009_PsFLoren/lib_protocol/script_repr.ml b/src/proto_009_PsFLoren/lib_protocol/script_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..d7fefc5a5483ab6a90cded0c9baebe805dbbe046 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_repr.ml @@ -0,0 +1,265 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type location = Micheline.canonical_location + +let location_encoding = Micheline.canonical_location_encoding + +type annot = Micheline.annot + +type expr = Michelson_v1_primitives.prim Micheline.canonical + +type lazy_expr = expr Data_encoding.lazy_t + +type node = (location, Michelson_v1_primitives.prim) Micheline.node + +let expr_encoding = + Micheline.canonical_encoding_v1 + ~variant:"michelson_v1" + Michelson_v1_primitives.prim_encoding + +type error += Lazy_script_decode (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"invalid_binary_format" + ~title:"Invalid binary format" + ~description: + "Could not deserialize some piece of data from its binary representation" + Data_encoding.empty + (function Lazy_script_decode -> Some () | _ -> None) + (fun () -> Lazy_script_decode) + +let lazy_expr_encoding = Data_encoding.lazy_encoding expr_encoding + +let lazy_expr expr = Data_encoding.make_lazy expr_encoding expr + +type t = {code : lazy_expr; storage : lazy_expr} + +let encoding = + let open Data_encoding in + def "scripted.contracts" + @@ conv + (fun {code; storage} -> (code, storage)) + (fun (code, storage) -> {code; storage}) + (obj2 (req "code" lazy_expr_encoding) (req "storage" lazy_expr_encoding)) + +let int_node_size_of_numbits n = (1, 1 + ((n + 63) / 64)) + +let int_node_size n = int_node_size_of_numbits (Z.numbits n) + +let string_node_size_of_length s = (1, 1 + ((s + 7) / 8)) + +let string_node_size s = string_node_size_of_length (String.length s) + +let bytes_node_size_of_length s = + (* approx cost of indirection to the C heap *) + (2, 1 + ((s + 7) / 8) + 12) + +let bytes_node_size s = bytes_node_size_of_length (Bytes.length s) + +let prim_node_size_nonrec_of_lengths n_args annots = + let annots_length = + List.fold_left (fun acc s -> acc + String.length s) 0 annots + in + if Compare.Int.(annots_length = 0) then (1 + n_args, 2 + (2 * n_args)) + else (2 + n_args, 4 + (2 * n_args) + ((annots_length + 7) / 8)) + +let prim_node_size_nonrec args annots = + let n_args = List.length args in + prim_node_size_nonrec_of_lengths n_args annots + +let seq_node_size_nonrec_of_length n_args = (1 + n_args, 2 + (2 * n_args)) + +let seq_node_size_nonrec args = + let n_args = List.length args in + seq_node_size_nonrec_of_length n_args + +module S = Saturation_repr + +let convert_pair (i1, i2) = (S.safe_int i1, S.safe_int i2) + +let rec node_size node = + let open Micheline in + match node with + | Int (_, n) -> + convert_pair (int_node_size n) + | String (_, s) -> + convert_pair (string_node_size s) + | Bytes (_, s) -> + convert_pair (bytes_node_size s) + | Prim (_, _, args, annot) -> + List.fold_left + (fun (blocks, words) node -> + let (nblocks, nwords) = node_size node in + (S.add blocks nblocks, S.add words nwords)) + (convert_pair (prim_node_size_nonrec args annot)) + args + | Seq (_, args) -> + List.fold_left + (fun (blocks, words) node -> + let (nblocks, nwords) = node_size node in + (S.add blocks nblocks, S.add words nwords)) + (convert_pair (seq_node_size_nonrec args)) + args + +let expr_size expr = node_size (Micheline.root expr) + +let traversal_cost node = + let (blocks, _words) = node_size node in + Gas_limit_repr.step_cost blocks + +let cost_of_size (blocks, words) = + let open Gas_limit_repr in + (S.sub blocks (S.safe_int 1) *@ alloc_cost S.zero) + +@ alloc_cost words +@ step_cost blocks + +let cost_of_size_int pair = cost_of_size (convert_pair pair) + +let int_node_cost n = cost_of_size_int (int_node_size n) + +let int_node_cost_of_numbits n = cost_of_size_int (int_node_size_of_numbits n) + +let string_node_cost s = cost_of_size_int (string_node_size s) + +let string_node_cost_of_length s = + cost_of_size_int (string_node_size_of_length s) + +let bytes_node_cost s = cost_of_size_int (bytes_node_size s) + +let bytes_node_cost_of_length s = + cost_of_size_int (bytes_node_size_of_length s) + +let prim_node_cost_nonrec args annot = + cost_of_size_int (prim_node_size_nonrec args annot) + +let seq_node_cost_nonrec args = cost_of_size_int (seq_node_size_nonrec args) + +let seq_node_cost_nonrec_of_length n_args = + cost_of_size_int (seq_node_size_nonrec_of_length n_args) + +let deserialized_cost expr = cost_of_size (expr_size expr) + +let serialized_cost bytes = + let open Gas_limit_repr in + alloc_bytes_cost (Bytes.length bytes) + +let force_decode lexpr = + let account_deserialization_cost = + Data_encoding.apply_lazy + ~fun_value:(fun _ -> false) + ~fun_bytes:(fun _ -> true) + ~fun_combine:(fun _ _ -> false) + lexpr + in + match Data_encoding.force_decode lexpr with + | Some v -> + if account_deserialization_cost then ok (v, deserialized_cost v) + else ok (v, Gas_limit_repr.free) + | None -> + error Lazy_script_decode + +let force_bytes expr = + let open Gas_limit_repr in + let account_serialization_cost = + Data_encoding.apply_lazy + ~fun_value:(fun v -> Some v) + ~fun_bytes:(fun _ -> None) + ~fun_combine:(fun _ _ -> None) + expr + in + match Data_encoding.force_bytes expr with + | bytes -> ( + match account_serialization_cost with + | Some v -> + ok (bytes, traversal_cost (Micheline.root v) +@ serialized_cost bytes) + | None -> + ok (bytes, Gas_limit_repr.free) ) + | exception _ -> + error Lazy_script_decode + +let minimal_deserialize_cost lexpr = + Data_encoding.apply_lazy + ~fun_value:(fun _ -> Gas_limit_repr.free) + ~fun_bytes:(fun b -> serialized_cost b) + ~fun_combine:(fun c_free _ -> c_free) + lexpr + +let unit = + Micheline.strip_locations (Prim (0, Michelson_v1_primitives.D_Unit, [], [])) + +let unit_parameter = lazy_expr unit + +let is_unit_parameter = + let unit_bytes = Data_encoding.force_bytes unit_parameter in + Data_encoding.apply_lazy + ~fun_value:(fun v -> + match Micheline.root v with + | Prim (_, Michelson_v1_primitives.D_Unit, [], []) -> + true + | _ -> + false) + ~fun_bytes:(fun b -> Compare.Bytes.equal b unit_bytes) + ~fun_combine:(fun res _ -> res) + +let rec strip_annotations node = + let open Micheline in + match node with + | (Int (_, _) | String (_, _) | Bytes (_, _)) as leaf -> + leaf + | Prim (loc, name, args, _) -> + Prim (loc, name, List.map strip_annotations args, []) + | Seq (loc, args) -> + Seq (loc, List.map strip_annotations args) + +let rec micheline_nodes node acc k = + match node with + | Micheline.Int (_, _) -> + k (acc + 1) + | Micheline.String (_, _) -> + k (acc + 1) + | Micheline.Bytes (_, _) -> + k (acc + 1) + | Micheline.Prim (_, _, subterms, _) -> + micheline_nodes_list subterms (acc + 1) k + | Micheline.Seq (_, subterms) -> + micheline_nodes_list subterms (acc + 1) k + +and micheline_nodes_list subterms acc k = + match subterms with + | [] -> + k acc + | n :: nodes -> + micheline_nodes_list nodes acc (fun acc -> micheline_nodes n acc k) + +let micheline_nodes node = micheline_nodes node 0 (fun x -> x) + +let cost_MICHELINE_STRIP_LOCATIONS size = + S.mul (S.safe_int size) (S.safe_int 100) + +let strip_locations_cost node = + let nodes = micheline_nodes node in + Gas_limit_repr.atomic_step_cost (cost_MICHELINE_STRIP_LOCATIONS nodes) diff --git a/src/proto_009_PsFLoren/lib_protocol/script_repr.mli b/src/proto_009_PsFLoren/lib_protocol/script_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..d78c39e3aadb74867c8a55cdca296bbd2d7b215e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_repr.mli @@ -0,0 +1,88 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type location = Micheline.canonical_location + +type annot = Micheline.annot + +type expr = Michelson_v1_primitives.prim Micheline.canonical + +type error += Lazy_script_decode (* `Permanent *) + +type lazy_expr = expr Data_encoding.lazy_t + +type node = (location, Michelson_v1_primitives.prim) Micheline.node + +val location_encoding : location Data_encoding.t + +val expr_encoding : expr Data_encoding.t + +val lazy_expr_encoding : lazy_expr Data_encoding.t + +val lazy_expr : expr -> lazy_expr + +type t = {code : lazy_expr; storage : lazy_expr} + +val encoding : t Data_encoding.encoding + +val deserialized_cost : expr -> Gas_limit_repr.cost + +val serialized_cost : bytes -> Gas_limit_repr.cost + +val traversal_cost : node -> Gas_limit_repr.cost + +val int_node_cost : Z.t -> Gas_limit_repr.cost + +val int_node_cost_of_numbits : int -> Gas_limit_repr.cost + +val string_node_cost : string -> Gas_limit_repr.cost + +val string_node_cost_of_length : int -> Gas_limit_repr.cost + +val bytes_node_cost : bytes -> Gas_limit_repr.cost + +val bytes_node_cost_of_length : int -> Gas_limit_repr.cost + +val prim_node_cost_nonrec : expr list -> annot -> Gas_limit_repr.cost + +val seq_node_cost_nonrec : expr list -> Gas_limit_repr.cost + +val seq_node_cost_nonrec_of_length : int -> Gas_limit_repr.cost + +val force_decode : lazy_expr -> (expr * Gas_limit_repr.cost) tzresult + +val force_bytes : lazy_expr -> (bytes * Gas_limit_repr.cost) tzresult + +val minimal_deserialize_cost : lazy_expr -> Gas_limit_repr.cost + +val unit_parameter : lazy_expr + +val is_unit_parameter : lazy_expr -> bool + +val strip_annotations : node -> node + +val micheline_nodes : node -> int + +val strip_locations_cost : node -> Gas_limit_repr.cost diff --git a/src/proto_009_PsFLoren/lib_protocol/script_tc_errors.ml b/src/proto_009_PsFLoren/lib_protocol/script_tc_errors.ml new file mode 100644 index 0000000000000000000000000000000000000000..412d9f729a9b269dd8620cefc39edff9b910d675 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_tc_errors.ml @@ -0,0 +1,191 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script + +(* ---- Error definitions ---------------------------------------------------*) + +type kind = Int_kind | String_kind | Bytes_kind | Prim_kind | Seq_kind + +type unparsed_stack_ty = (Script.expr * Script.annot) list + +type type_map = (int * (unparsed_stack_ty * unparsed_stack_ty)) list + +(* Structure errors *) +type error += Invalid_arity of Script.location * prim * int * int + +type error += Invalid_seq_arity of Script.location * int * int + +type error += + | Invalid_namespace of + Script.location + * prim + * Michelson_v1_primitives.namespace + * Michelson_v1_primitives.namespace + +type error += Invalid_primitive of Script.location * prim list * prim + +type error += Invalid_kind of Script.location * kind list * kind + +type error += Invalid_never_expr of Script.location + +type error += Missing_field of prim + +type error += Duplicate_field of Script.location * prim + +type error += Unexpected_lazy_storage of Script.location + +type error += Unexpected_operation of Script.location + +type error += Unexpected_contract of Script.location + +type error += No_such_entrypoint of string + +type error += Duplicate_entrypoint of string + +type error += Unreachable_entrypoint of prim list + +type error += Entrypoint_name_too_long of string + +(* Instruction typing errors *) +type error += Fail_not_in_tail_position of Script.location + +type error += + | Undefined_binop : + Script.location * prim * Script.expr * Script.expr + -> error + +type error += Undefined_unop : Script.location * prim * Script.expr -> error + +type error += + | Bad_return : Script.location * unparsed_stack_ty * Script.expr -> error + +type error += + | Bad_stack : Script.location * prim * int * unparsed_stack_ty -> error + +type error += + | Unmatched_branches : + Script.location * unparsed_stack_ty * unparsed_stack_ty + -> error + +type error += Self_in_lambda of Script.location + +type error += Bad_stack_length + +type error += Bad_stack_item of int + +type error += Inconsistent_annotations of string * string + +type error += + | Inconsistent_type_annotations : + Script.location * Script.expr * Script.expr + -> error + +type error += Inconsistent_field_annotations of string * string + +type error += Unexpected_annotation of Script.location + +type error += Ungrouped_annotations of Script.location + +type error += Invalid_map_body : Script.location * unparsed_stack_ty -> error + +type error += Invalid_map_block_fail of Script.location + +type error += + | Invalid_iter_body : + Script.location * unparsed_stack_ty * unparsed_stack_ty + -> error + +type error += Type_too_large : Script.location * int * int -> error + +type error += Pair_bad_argument of Script.location + +type error += Unpair_bad_argument of Script.location + +type error += Dup_n_bad_argument of Script.location + +type error += Dup_n_bad_stack of Script.location + +(* Value typing errors *) +type error += + | Invalid_constant : Script.location * Script.expr * Script.expr -> error + +type error += + | Invalid_syntactic_constant : + Script.location * Script.expr * string + -> error + +type error += Invalid_contract of Script.location * Contract.t + +type error += Invalid_big_map of Script.location * Big_map.Id.t + +type error += + | Comparable_type_expected : Script.location * Script.expr -> error + +type error += Inconsistent_types : Script.expr * Script.expr -> error + +type error += + | Inconsistent_memo_sizes : + Sapling.Memo_size.t * Sapling.Memo_size.t + -> error + +type error += Unordered_map_keys of Script.location * Script.expr + +type error += Unordered_set_values of Script.location * Script.expr + +type error += Duplicate_map_keys of Script.location * Script.expr + +type error += Duplicate_set_values of Script.location * Script.expr + +(* Toplevel errors *) +type error += + | Ill_typed_data : string option * Script.expr * Script.expr -> error + +type error += + | Ill_formed_type of string option * Script.expr * Script.location + +type error += Ill_typed_contract : Script.expr * type_map -> error + +(* Gas related errors *) +type error += Cannot_serialize_error + +(* Deprecation errors *) +type error += Deprecated_instruction of prim + +(* Stackoverflow errors *) +type error += Typechecking_too_many_recursive_calls + +type error += Unparsing_too_many_recursive_calls + +(* Ticket errors *) +type error += Unexpected_ticket of Script.location + +type error += Unexpected_forged_value of Script.location + +type error += Non_dupable_type of Script.location * Script.expr + +(* Impossible errors *) +type error += Unparsing_invariant_violated diff --git a/src/proto_009_PsFLoren/lib_protocol/script_tc_errors_registration.ml b/src/proto_009_PsFLoren/lib_protocol/script_tc_errors_registration.ml new file mode 100644 index 0000000000000000000000000000000000000000..cb62174f77affc1a47eb239ff5f4b92b9d9e7946 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_tc_errors_registration.ml @@ -0,0 +1,778 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script +open Script_tc_errors + +(* Helpers for encoding *) +let type_map_enc = + let open Data_encoding in + let stack_enc = list (tup2 Script.expr_encoding (list string)) in + list + (conv + (fun (loc, (bef, aft)) -> (loc, bef, aft)) + (fun (loc, bef, aft) -> (loc, (bef, aft))) + (obj3 + (req "location" Script.location_encoding) + (req "stack_before" stack_enc) + (req "stack_after" stack_enc))) + +let stack_ty_enc = + let open Data_encoding in + list (obj2 (req "type" Script.expr_encoding) (dft "annots" (list string) [])) + +(* main registration *) +let () = + let open Data_encoding in + let located enc = + merge_objs (obj1 (req "location" Script.location_encoding)) enc + in + let arity_enc = int8 in + let namespace_enc = + def + "primitiveNamespace" + ~title:"Primitive namespace" + ~description: + "One of the four possible namespaces of primitive (data constructor, \ + type name, instruction or keyword)." + @@ string_enum + [ ("type", Michelson_v1_primitives.Type_namespace); + ("constant", Constant_namespace); + ("instruction", Instr_namespace); + ("keyword", Keyword_namespace) ] + in + let kind_enc = + def + "expressionKind" + ~title:"Expression kind" + ~description: + "One of the four possible kinds of expression (integer, string, \ + primitive application or sequence)." + @@ string_enum + [ ("integer", Int_kind); + ("string", String_kind); + ("bytes", Bytes_kind); + ("primitiveApplication", Prim_kind); + ("sequence", Seq_kind) ] + in + (* -- Structure errors ---------------------- *) + (* Invalid arity *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_arity" + ~title:"Invalid arity" + ~description: + "In a script or data expression, a primitive was applied to an \ + unsupported number of arguments." + (located + (obj3 + (req "primitive_name" Script.prim_encoding) + (req "expected_arity" arity_enc) + (req "wrong_arity" arity_enc))) + (function + | Invalid_arity (loc, name, exp, got) -> + Some (loc, (name, exp, got)) + | _ -> + None) + (fun (loc, (name, exp, got)) -> Invalid_arity (loc, name, exp, got)) ; + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_seq_arity" + ~title:"Invalid sequence arity" + ~description: + "In a script or data expression, a sequence was used with a number of \ + elements too small." + (located + (obj2 + (req "minimal_expected_arity" arity_enc) + (req "wrong_arity" arity_enc))) + (function + | Invalid_seq_arity (loc, exp, got) -> Some (loc, (exp, got)) | _ -> None) + (fun (loc, (exp, got)) -> Invalid_seq_arity (loc, exp, got)) ; + (* Missing field *) + register_error_kind + `Permanent + ~id:"michelson_v1.missing_script_field" + ~title:"Script is missing a field (parse error)" + ~description:"When parsing script, a field was expected, but not provided" + (obj1 (req "prim" prim_encoding)) + (function Missing_field prim -> Some prim | _ -> None) + (fun prim -> Missing_field prim) ; + (* Invalid primitive *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_primitive" + ~title:"Invalid primitive" + ~description:"In a script or data expression, a primitive was unknown." + (located + (obj2 + (dft "expected_primitive_names" (list prim_encoding) []) + (req "wrong_primitive_name" prim_encoding))) + (function + | Invalid_primitive (loc, exp, got) -> Some (loc, (exp, got)) | _ -> None) + (fun (loc, (exp, got)) -> Invalid_primitive (loc, exp, got)) ; + (* Invalid kind *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_expression_kind" + ~title:"Invalid expression kind" + ~description: + "In a script or data expression, an expression was of the wrong kind \ + (for instance a string where only a primitive applications can appear)." + (located + (obj2 (req "expected_kinds" (list kind_enc)) (req "wrong_kind" kind_enc))) + (function + | Invalid_kind (loc, exp, got) -> Some (loc, (exp, got)) | _ -> None) + (fun (loc, (exp, got)) -> Invalid_kind (loc, exp, got)) ; + (* Invalid namespace *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_primitive_namespace" + ~title:"Invalid primitive namespace" + ~description: + "In a script or data expression, a primitive was of the wrong namespace." + (located + (obj3 + (req "primitive_name" prim_encoding) + (req "expected_namespace" namespace_enc) + (req "wrong_namespace" namespace_enc))) + (function + | Invalid_namespace (loc, name, exp, got) -> + Some (loc, (name, exp, got)) + | _ -> + None) + (fun (loc, (name, exp, got)) -> Invalid_namespace (loc, name, exp, got)) ; + (* Invalid literal for type never *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_never_expr" + ~title:"Invalid expression for type never" + ~description: + "In a script or data expression, an expression was provided but a value \ + of type never was expected. No expression can have type never." + (located unit) + (function Invalid_never_expr loc -> Some (loc, ()) | _ -> None) + (fun (loc, ()) -> Invalid_never_expr loc) ; + (* Duplicate field *) + register_error_kind + `Permanent + ~id:"michelson_v1.duplicate_script_field" + ~title:"Script has a duplicated field (parse error)" + ~description:"When parsing script, a field was found more than once" + (obj2 (req "loc" location_encoding) (req "prim" prim_encoding)) + (function Duplicate_field (loc, prim) -> Some (loc, prim) | _ -> None) + (fun (loc, prim) -> Duplicate_field (loc, prim)) ; + (* Unexpected big_map *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_lazy_storage" + ~title:"Lazy storage in unauthorized position (type error)" + ~description: + "When parsing script, a big_map or sapling_state type was found in a \ + position where it could end up stored inside a big_map, which is \ + forbidden for now." + (obj1 (req "loc" location_encoding)) + (function Unexpected_lazy_storage loc -> Some loc | _ -> None) + (fun loc -> Unexpected_lazy_storage loc) ; + (* Unexpected operation *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_operation" + ~title:"Operation in unauthorized position (type error)" + ~description: + "When parsing script, an operation type was found in the storage or \ + parameter field." + (obj1 (req "loc" location_encoding)) + (function Unexpected_operation loc -> Some loc | _ -> None) + (fun loc -> Unexpected_operation loc) ; + (* No such entrypoint *) + register_error_kind + `Permanent + ~id:"michelson_v1.no_such_entrypoint" + ~title:"No such entrypoint (type error)" + ~description:"An entrypoint was not found when calling a contract." + (obj1 (req "entrypoint" string)) + (function No_such_entrypoint entrypoint -> Some entrypoint | _ -> None) + (fun entrypoint -> No_such_entrypoint entrypoint) ; + (* Unreachable entrypoint *) + register_error_kind + `Permanent + ~id:"michelson_v1.unreachable_entrypoint" + ~title:"Unreachable entrypoint (type error)" + ~description:"An entrypoint in the contract is not reachable." + (obj1 (req "path" (list prim_encoding))) + (function Unreachable_entrypoint path -> Some path | _ -> None) + (fun path -> Unreachable_entrypoint path) ; + (* Duplicate entrypoint *) + register_error_kind + `Permanent + ~id:"michelson_v1.duplicate_entrypoint" + ~title:"Duplicate entrypoint (type error)" + ~description:"Two entrypoints have the same name." + (obj1 (req "path" string)) + (function Duplicate_entrypoint entrypoint -> Some entrypoint | _ -> None) + (fun entrypoint -> Duplicate_entrypoint entrypoint) ; + (* Entrypoint name too long *) + register_error_kind + `Permanent + ~id:"michelson_v1.entrypoint_name_too_long" + ~title:"Entrypoint name too long (type error)" + ~description: + "An entrypoint name exceeds the maximum length of 31 characters." + (obj1 (req "name" string)) + (function + | Entrypoint_name_too_long entrypoint -> Some entrypoint | _ -> None) + (fun entrypoint -> Entrypoint_name_too_long entrypoint) ; + (* Unexpected contract *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_contract" + ~title:"Contract in unauthorized position (type error)" + ~description: + "When parsing script, a contract type was found in the storage or \ + parameter field." + (obj1 (req "loc" location_encoding)) + (function Unexpected_contract loc -> Some loc | _ -> None) + (fun loc -> Unexpected_contract loc) ; + (* -- Value typing errors ---------------------- *) + (* Unordered map keys *) + register_error_kind + `Permanent + ~id:"michelson_v1.unordered_map_literal" + ~title:"Invalid map key order" + ~description:"Map keys must be in strictly increasing order" + (obj2 + (req "location" Script.location_encoding) + (req "item" Script.expr_encoding)) + (function Unordered_map_keys (loc, expr) -> Some (loc, expr) | _ -> None) + (fun (loc, expr) -> Unordered_map_keys (loc, expr)) ; + (* Duplicate map keys *) + register_error_kind + `Permanent + ~id:"michelson_v1.duplicate_map_keys" + ~title:"Duplicate map keys" + ~description:"Map literals cannot contain duplicated keys" + (obj2 + (req "location" Script.location_encoding) + (req "item" Script.expr_encoding)) + (function Duplicate_map_keys (loc, expr) -> Some (loc, expr) | _ -> None) + (fun (loc, expr) -> Duplicate_map_keys (loc, expr)) ; + (* Unordered set values *) + register_error_kind + `Permanent + ~id:"michelson_v1.unordered_set_literal" + ~title:"Invalid set value order" + ~description:"Set values must be in strictly increasing order" + (obj2 + (req "location" Script.location_encoding) + (req "value" Script.expr_encoding)) + (function + | Unordered_set_values (loc, expr) -> Some (loc, expr) | _ -> None) + (fun (loc, expr) -> Unordered_set_values (loc, expr)) ; + (* Duplicate set values *) + register_error_kind + `Permanent + ~id:"michelson_v1.duplicate_set_values_in_literal" + ~title:"Sets literals cannot contain duplicate elements" + ~description: + "Set literals cannot contain duplicate elements, but a duplicate was \ + found while parsing." + (obj2 + (req "location" Script.location_encoding) + (req "value" Script.expr_encoding)) + (function + | Duplicate_set_values (loc, expr) -> Some (loc, expr) | _ -> None) + (fun (loc, expr) -> Duplicate_set_values (loc, expr)) ; + (* -- Instruction typing errors ------------- *) + (* Fail not in tail position *) + register_error_kind + `Permanent + ~id:"michelson_v1.fail_not_in_tail_position" + ~title:"FAIL not in tail position" + ~description:"There is non trivial garbage code after a FAIL instruction." + (located empty) + (function Fail_not_in_tail_position loc -> Some (loc, ()) | _ -> None) + (fun (loc, ()) -> Fail_not_in_tail_position loc) ; + (* Undefined binary operation *) + register_error_kind + `Permanent + ~id:"michelson_v1.undefined_binop" + ~title:"Undefined binop" + ~description: + "A binary operation is called on operands of types over which it is not \ + defined." + (located + (obj3 + (req "operator_name" prim_encoding) + (req "wrong_left_operand_type" Script.expr_encoding) + (req "wrong_right_operand_type" Script.expr_encoding))) + (function + | Undefined_binop (loc, n, tyl, tyr) -> + Some (loc, (n, tyl, tyr)) + | _ -> + None) + (fun (loc, (n, tyl, tyr)) -> Undefined_binop (loc, n, tyl, tyr)) ; + (* Undefined unary operation *) + register_error_kind + `Permanent + ~id:"michelson_v1.undefined_unop" + ~title:"Undefined unop" + ~description: + "A unary operation is called on an operand of type over which it is not \ + defined." + (located + (obj2 + (req "operator_name" prim_encoding) + (req "wrong_operand_type" Script.expr_encoding))) + (function Undefined_unop (loc, n, ty) -> Some (loc, (n, ty)) | _ -> None) + (fun (loc, (n, ty)) -> Undefined_unop (loc, n, ty)) ; + (* Bad return *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_return" + ~title:"Bad return" + ~description:"Unexpected stack at the end of a lambda or script." + (located + (obj2 + (req "expected_return_type" Script.expr_encoding) + (req "wrong_stack_type" stack_ty_enc))) + (function Bad_return (loc, sty, ty) -> Some (loc, (ty, sty)) | _ -> None) + (fun (loc, (ty, sty)) -> Bad_return (loc, sty, ty)) ; + (* Bad stack *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_stack" + ~title:"Bad stack" + ~description:"The stack has an unexpected length or contents." + (located + (obj3 + (req "primitive_name" prim_encoding) + (req "relevant_stack_portion" int16) + (req "wrong_stack_type" stack_ty_enc))) + (function + | Bad_stack (loc, name, s, sty) -> Some (loc, (name, s, sty)) | _ -> None) + (fun (loc, (name, s, sty)) -> Bad_stack (loc, name, s, sty)) ; + (* Inconsistent annotations *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_annotations" + ~title:"Annotations inconsistent between branches" + ~description:"The annotations on two types could not be merged" + (obj2 (req "annot1" string) (req "annot2" string)) + (function + | Inconsistent_annotations (annot1, annot2) -> + Some (annot1, annot2) + | _ -> + None) + (fun (annot1, annot2) -> Inconsistent_annotations (annot1, annot2)) ; + (* Inconsistent field annotations *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_field_annotations" + ~title:"Annotations for field accesses is inconsistent" + ~description: + "The specified field does not match the field annotation in the type" + (obj2 (req "annot1" string) (req "annot2" string)) + (function + | Inconsistent_field_annotations (annot1, annot2) -> + Some (annot1, annot2) + | _ -> + None) + (fun (annot1, annot2) -> Inconsistent_field_annotations (annot1, annot2)) ; + (* Inconsistent type annotations *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_type_annotations" + ~title:"Types contain inconsistent annotations" + ~description:"The two types contain annotations that do not match" + (located + (obj2 + (req "type1" Script.expr_encoding) + (req "type2" Script.expr_encoding))) + (function + | Inconsistent_type_annotations (loc, ty1, ty2) -> + Some (loc, (ty1, ty2)) + | _ -> + None) + (fun (loc, (ty1, ty2)) -> Inconsistent_type_annotations (loc, ty1, ty2)) ; + (* Unexpected annotation *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_annotation" + ~title:"An annotation was encountered where no annotation is expected" + ~description:"A node in the syntax tree was improperly annotated" + (located empty) + (function Unexpected_annotation loc -> Some (loc, ()) | _ -> None) + (fun (loc, ()) -> Unexpected_annotation loc) ; + (* Ungrouped annotations *) + register_error_kind + `Permanent + ~id:"michelson_v1.ungrouped_annotations" + ~title:"Annotations of the same kind were found spread apart" + ~description:"Annotations of the same kind must be grouped" + (located empty) + (function Ungrouped_annotations loc -> Some (loc, ()) | _ -> None) + (fun (loc, ()) -> Ungrouped_annotations loc) ; + (* Unmatched branches *) + register_error_kind + `Permanent + ~id:"michelson_v1.unmatched_branches" + ~title:"Unmatched branches" + ~description: + "At the join point at the end of two code branches the stacks have \ + inconsistent lengths or contents." + (located + (obj2 + (req "first_stack_type" stack_ty_enc) + (req "other_stack_type" stack_ty_enc))) + (function + | Unmatched_branches (loc, stya, styb) -> + Some (loc, (stya, styb)) + | _ -> + None) + (fun (loc, (stya, styb)) -> Unmatched_branches (loc, stya, styb)) ; + (* Bad stack item *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_stack_item" + ~title:"Bad stack item" + ~description: + "The type of a stack item is unexpected (this error is always \ + accompanied by a more precise one)." + (obj1 (req "item_level" int16)) + (function Bad_stack_item n -> Some n | _ -> None) + (fun n -> Bad_stack_item n) ; + (* SELF in lambda *) + register_error_kind + `Permanent + ~id:"michelson_v1.self_in_lambda" + ~title:"SELF instruction in lambda" + ~description:"A SELF instruction was encountered in a lambda expression." + (located empty) + (function Self_in_lambda loc -> Some (loc, ()) | _ -> None) + (fun (loc, ()) -> Self_in_lambda loc) ; + (* Bad stack length *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_stack_lengths" + ~title:"Inconsistent stack lengths" + ~description: + "A stack was of an unexpected length (this error is always in the \ + context of a located error)." + empty + (function Bad_stack_length -> Some () | _ -> None) + (fun () -> Bad_stack_length) ; + (* -- Value typing errors ------------------- *) + (* Invalid constant *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_constant" + ~title:"Invalid constant" + ~description:"A data expression was invalid for its expected type." + (located + (obj2 + (req "expected_type" Script.expr_encoding) + (req "wrong_expression" Script.expr_encoding))) + (function + | Invalid_constant (loc, expr, ty) -> Some (loc, (ty, expr)) | _ -> None) + (fun (loc, (ty, expr)) -> Invalid_constant (loc, expr, ty)) ; + (* Invalid syntactic constant *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_syntactic_constant" + ~title:"Invalid constant (parse error)" + ~description:"A compile-time constant was invalid for its expected form." + (located + (obj2 + (req "expected_form" string) + (req "wrong_expression" Script.expr_encoding))) + (function + | Invalid_syntactic_constant (loc, expr, expected) -> + Some (loc, (expected, expr)) + | _ -> + None) + (fun (loc, (expected, expr)) -> + Invalid_syntactic_constant (loc, expr, expected)) ; + (* Invalid contract *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_contract" + ~title:"Invalid contract" + ~description: + "A script or data expression references a contract that does not exist \ + or assumes a wrong type for an existing contract." + (located (obj1 (req "contract" Contract.encoding))) + (function Invalid_contract (loc, c) -> Some (loc, c) | _ -> None) + (fun (loc, c) -> Invalid_contract (loc, c)) ; + (* Invalid big_map *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_big_map" + ~title:"Invalid big_map" + ~description: + "A script or data expression references a big_map that does not exist \ + or assumes a wrong type for an existing big_map." + (located (obj1 (req "big_map" Big_map.Id.encoding))) + (function Invalid_big_map (loc, c) -> Some (loc, c) | _ -> None) + (fun (loc, c) -> Invalid_big_map (loc, c)) ; + (* Comparable type expected *) + register_error_kind + `Permanent + ~id:"michelson_v1.comparable_type_expected" + ~title:"Comparable type expected" + ~description: + "A non comparable type was used in a place where only comparable types \ + are accepted." + (located (obj1 (req "wrong_type" Script.expr_encoding))) + (function + | Comparable_type_expected (loc, ty) -> Some (loc, ty) | _ -> None) + (fun (loc, ty) -> Comparable_type_expected (loc, ty)) ; + (* Inconsistent types *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_types" + ~title:"Inconsistent types" + ~description: + "This is the basic type clash error, that appears in several places \ + where the equality of two types have to be proven, it is always \ + accompanied with another error that provides more context." + (obj2 + (req "first_type" Script.expr_encoding) + (req "other_type" Script.expr_encoding)) + (function Inconsistent_types (tya, tyb) -> Some (tya, tyb) | _ -> None) + (fun (tya, tyb) -> Inconsistent_types (tya, tyb)) ; + (* Inconsistent memo_sizes *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_memo_sizes" + ~title:"Inconsistent memo sizes" + ~description: + "Memo sizes of two sapling states or transactions do not match" + (obj2 + (req "first_memo_size" Sapling.Memo_size.encoding) + (req "other_memo_size" Sapling.Memo_size.encoding)) + (function + | Inconsistent_memo_sizes (msa, msb) -> Some (msa, msb) | _ -> None) + (fun (msa, msb) -> Inconsistent_memo_sizes (msa, msb)) ; + (* -- Instruction typing errors ------------------- *) + (* Invalid map body *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_map_body" + ~title:"Invalid map body" + ~description:"The body of a map block did not match the expected type" + (obj2 (req "loc" Script.location_encoding) (req "body_type" stack_ty_enc)) + (function Invalid_map_body (loc, stack) -> Some (loc, stack) | _ -> None) + (fun (loc, stack) -> Invalid_map_body (loc, stack)) ; + (* Invalid map block FAIL *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_map_block_fail" + ~title:"FAIL instruction occurred as body of map block" + ~description: + "FAIL cannot be the only instruction in the body. The proper type of \ + the return list cannot be inferred." + (obj1 (req "loc" Script.location_encoding)) + (function Invalid_map_block_fail loc -> Some loc | _ -> None) + (fun loc -> Invalid_map_block_fail loc) ; + (* Invalid ITER body *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_iter_body" + ~title:"ITER body returned wrong stack type" + ~description: + "The body of an ITER instruction must result in the same stack type as \ + before the ITER." + (obj3 + (req "loc" Script.location_encoding) + (req "bef_stack" stack_ty_enc) + (req "aft_stack" stack_ty_enc)) + (function + | Invalid_iter_body (loc, bef, aft) -> Some (loc, bef, aft) | _ -> None) + (fun (loc, bef, aft) -> Invalid_iter_body (loc, bef, aft)) ; + (* Type too large *) + register_error_kind + `Permanent + ~id:"michelson_v1.type_too_large" + ~title:"Stack item type too large" + ~description:"An instruction generated a type larger than the limit." + (obj3 + (req "loc" Script.location_encoding) + (req "type_size" uint16) + (req "maximum_type_size" uint16)) + (function + | Type_too_large (loc, ts, maxts) -> Some (loc, ts, maxts) | _ -> None) + (fun (loc, ts, maxts) -> Type_too_large (loc, ts, maxts)) ; + (* Bad PAIR argument *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_pair_argument" + ~title:"0 or 1 passed to PAIR" + ~description:"PAIR expects an argument of at least 2" + (obj1 (req "loc" Script.location_encoding)) + (function Pair_bad_argument loc -> Some loc | _ -> None) + (fun loc -> Pair_bad_argument loc) ; + (* Bad UNPAIR argument *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_unpair_argument" + ~title:"0 or 1 passed to UNPAIR" + ~description:"UNPAIR expects an argument of at least 2" + (obj1 (req "loc" Script.location_encoding)) + (function Unpair_bad_argument loc -> Some loc | _ -> None) + (fun loc -> Unpair_bad_argument loc) ; + (* Bad dup_n argument *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_dupn_argument" + ~title:"0 passed to DUP n" + ~description:"DUP expects an argument of at least 1 (passed 0)" + (obj1 (req "loc" Script.location_encoding)) + (function Dup_n_bad_argument loc -> Some loc | _ -> None) + (fun loc -> Dup_n_bad_argument loc) ; + (* Bad dup_n stack *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_dupn_stack" + ~title:"Stack too short when typing DUP n" + ~description:"Stack present when typing DUP n was too short" + (obj1 (req "loc" Script.location_encoding)) + (function Dup_n_bad_stack x -> Some x | _ -> None) + (fun x -> Dup_n_bad_stack x) ; + (* -- Toplevel errors ------------------- *) + (* Ill typed data *) + register_error_kind + `Permanent + ~id:"michelson_v1.ill_typed_data" + ~title:"Ill typed data" + ~description: + "The toplevel error thrown when trying to typecheck a data expression \ + against a given type (always followed by more precise errors)." + (obj3 + (opt "identifier" string) + (req "expected_type" Script.expr_encoding) + (req "ill_typed_expression" Script.expr_encoding)) + (function + | Ill_typed_data (name, expr, ty) -> Some (name, ty, expr) | _ -> None) + (fun (name, ty, expr) -> Ill_typed_data (name, expr, ty)) ; + (* Ill formed type *) + register_error_kind + `Permanent + ~id:"michelson_v1.ill_formed_type" + ~title:"Ill formed type" + ~description: + "The toplevel error thrown when trying to parse a type expression \ + (always followed by more precise errors)." + (obj3 + (opt "identifier" string) + (req "ill_formed_expression" Script.expr_encoding) + (req "location" Script.location_encoding)) + (function + | Ill_formed_type (name, expr, loc) -> Some (name, expr, loc) | _ -> None) + (fun (name, expr, loc) -> Ill_formed_type (name, expr, loc)) ; + (* Ill typed contract *) + register_error_kind + `Permanent + ~id:"michelson_v1.ill_typed_contract" + ~title:"Ill typed contract" + ~description: + "The toplevel error thrown when trying to typecheck a contract code \ + against given input, output and storage types (always followed by more \ + precise errors)." + (obj2 + (req "ill_typed_code" Script.expr_encoding) + (req "type_map" type_map_enc)) + (function + | Ill_typed_contract (expr, type_map) -> + Some (expr, type_map) + | _ -> + None) + (fun (expr, type_map) -> Ill_typed_contract (expr, type_map)) ; + (* Cannot serialize error *) + register_error_kind + `Temporary + ~id:"michelson_v1.cannot_serialize_error" + ~title:"Not enough gas to serialize error" + ~description:"The error was too big to be serialized with the provided gas" + Data_encoding.empty + (function Cannot_serialize_error -> Some () | _ -> None) + (fun () -> Cannot_serialize_error) ; + (* Deprecated instruction *) + register_error_kind + `Permanent + ~id:"michelson_v1.deprecated_instruction" + ~title:"Script is using a deprecated instruction" + ~description: + "A deprecated instruction usage is disallowed in newly created contracts" + (obj1 (req "prim" prim_encoding)) + (function Deprecated_instruction prim -> Some prim | _ -> None) + (fun prim -> Deprecated_instruction prim) ; + (* Typechecking stack overflow *) + register_error_kind + `Temporary + ~id:"michelson_v1.typechecking_too_many_recursive_calls" + ~title:"Too many recursive calls during typechecking" + ~description:"Too many recursive calls were needed for typechecking" + Data_encoding.empty + (function Typechecking_too_many_recursive_calls -> Some () | _ -> None) + (fun () -> Typechecking_too_many_recursive_calls) ; + (* Unparsing stack overflow *) + register_error_kind + `Temporary + ~id:"michelson_v1.unparsing_stack_overflow" + ~title:"Too many recursive calls during unparsing" + ~description:"Too many recursive calls were needed for unparsing" + Data_encoding.empty + (function Unparsing_too_many_recursive_calls -> Some () | _ -> None) + (fun () -> Unparsing_too_many_recursive_calls) ; + (* Unexpected forged value *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_forged_value" + ~title:"Unexpected forged value" + ~description: + "A forged value was encountered but disallowed for that position." + (obj1 (req "location" Script.location_encoding)) + (function Unexpected_forged_value loc -> Some loc | _ -> None) + (fun loc -> Unexpected_forged_value loc) ; + (* Unexpected ticket *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_ticket" + ~title:"Ticket in unauthorized position (type error)" + ~description:"A ticket type has been found" + (obj1 (req "loc" location_encoding)) + (function Unexpected_ticket loc -> Some loc | _ -> None) + (fun loc -> Unexpected_ticket loc) ; + (* Attempt to duplicate a non-dupable type *) + register_error_kind + `Permanent + ~id:"michelson_v1.non_dupable_type" + ~title:"Non-dupable type duplication attempt" + ~description:"DUP was used on a non-dupable type (e.g. tickets)." + (obj2 (req "loc" location_encoding) (req "type" Script.expr_encoding)) + (function Non_dupable_type (loc, ty) -> Some (loc, ty) | _ -> None) + (fun (loc, ty) -> Non_dupable_type (loc, ty)) diff --git a/src/proto_009_PsFLoren/lib_protocol/script_tc_errors_registration.mli b/src/proto_009_PsFLoren/lib_protocol/script_tc_errors_registration.mli new file mode 100644 index 0000000000000000000000000000000000000000..c8dd34c2e0bd7431f4ed2d0a75c91752fa0f7cc8 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_tc_errors_registration.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script + +val type_map_enc : + (location * ((expr * string list) list * (expr * string list) list)) list + Data_encoding.encoding + +val stack_ty_enc : (expr * string list) list Data_encoding.encoding diff --git a/src/proto_009_PsFLoren/lib_protocol/script_timestamp_repr.ml b/src/proto_009_PsFLoren/lib_protocol/script_timestamp_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..c8474e2e1d3ea7ed395c45c4a5ca9e53d708ba2e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_timestamp_repr.ml @@ -0,0 +1,57 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Z.t + +let compare = Z.compare + +let of_int64 = Z.of_int64 + +let of_string x = + match Time_repr.of_notation x with + | None -> ( + try Some (Z.of_string x) with _ -> None ) + | Some time -> + Some (of_int64 (Time_repr.to_seconds time)) + +let to_notation x = + try + let notation = Time_repr.to_notation (Time.of_seconds (Z.to_int64 x)) in + if String.equal notation "out_of_range" then None else Some notation + with _ -> None + +let to_num_str = Z.to_string + +let to_string x = match to_notation x with None -> to_num_str x | Some s -> s + +let diff x y = Script_int_repr.of_zint @@ Z.sub x y + +let sub_delta t delta = Z.sub t (Script_int_repr.to_zint delta) + +let add_delta t delta = Z.add t (Script_int_repr.to_zint delta) + +let to_zint x = x + +let of_zint x = x diff --git a/src/proto_009_PsFLoren/lib_protocol/script_timestamp_repr.mli b/src/proto_009_PsFLoren/lib_protocol/script_timestamp_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..7f2b156d2fabd4057844835c31e2c45ba5f6fc09 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_timestamp_repr.mli @@ -0,0 +1,53 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Script_int_repr + +type t + +val of_int64 : int64 -> t + +val compare : t -> t -> int + +(* Convert a timestamp to a notation if possible *) +val to_notation : t -> string option + +(* Convert a timestamp to a string representation of the seconds *) +val to_num_str : t -> string + +(* Convert to a notation if possible, or num if not *) +val to_string : t -> string + +val of_string : string -> t option + +val diff : t -> t -> z num + +val add_delta : t -> z num -> t + +val sub_delta : t -> z num -> t + +val to_zint : t -> Z.t + +val of_zint : Z.t -> t diff --git a/src/proto_009_PsFLoren/lib_protocol/script_typed_ir.ml b/src/proto_009_PsFLoren/lib_protocol/script_typed_ir.ml new file mode 100644 index 0000000000000000000000000000000000000000..502db7dd7e80a97ef36c3ba5fccf4ac07c6e47bc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/script_typed_ir.ml @@ -0,0 +1,564 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script_int + +(* ---- Auxiliary types -----------------------------------------------------*) + +type var_annot = Var_annot of string + +type type_annot = Type_annot of string + +type field_annot = Field_annot of string + +type address = Contract.t * string + +type ('a, 'b) pair = 'a * 'b + +type ('a, 'b) union = L of 'a | R of 'b + +type never = | + +type _ comparable_ty = + | Unit_key : type_annot option -> unit comparable_ty + | Never_key : type_annot option -> never comparable_ty + | Int_key : type_annot option -> z num comparable_ty + | Nat_key : type_annot option -> n num comparable_ty + | Signature_key : type_annot option -> signature comparable_ty + | String_key : type_annot option -> string comparable_ty + | Bytes_key : type_annot option -> Bytes.t comparable_ty + | Mutez_key : type_annot option -> Tez.t comparable_ty + | Bool_key : type_annot option -> bool comparable_ty + | Key_hash_key : type_annot option -> public_key_hash comparable_ty + | Key_key : type_annot option -> public_key comparable_ty + | Timestamp_key : type_annot option -> Script_timestamp.t comparable_ty + | Chain_id_key : type_annot option -> Chain_id.t comparable_ty + | Address_key : type_annot option -> address comparable_ty + | Pair_key : + ('a comparable_ty * field_annot option) + * ('b comparable_ty * field_annot option) + * type_annot option + -> ('a, 'b) pair comparable_ty + | Union_key : + ('a comparable_ty * field_annot option) + * ('b comparable_ty * field_annot option) + * type_annot option + -> ('a, 'b) union comparable_ty + | Option_key : + 'v comparable_ty * type_annot option + -> 'v option comparable_ty + +module type Boxed_set = sig + type elt + + val elt_ty : elt comparable_ty + + module OPS : S.SET with type elt = elt + + val boxed : OPS.t + + val size : int +end + +type 'elt set = (module Boxed_set with type elt = 'elt) + +module type Boxed_map = sig + type key + + type value + + val key_ty : key comparable_ty + + module OPS : S.MAP with type key = key + + val boxed : value OPS.t * int +end + +type ('key, 'value) map = + (module Boxed_map with type key = 'key and type value = 'value) + +module Big_map_overlay = Map.Make (struct + type t = Script_expr_hash.t + + let compare = Script_expr_hash.compare +end) + +type ('key, 'value) big_map_overlay = { + map : ('key * 'value option) Big_map_overlay.t; + size : int; +} + +type operation = packed_internal_operation * Lazy_storage.diffs option + +type 'a ticket = {ticketer : address; contents : 'a; amount : n num} + +type ('arg, 'storage) script = { + code : (('arg, 'storage) pair, (operation boxed_list, 'storage) pair) lambda; + arg_type : 'arg ty; + storage : 'storage; + storage_type : 'storage ty; + root_name : field_annot option; +} + +and end_of_stack = unit + +and ('arg, 'ret) lambda = + | Lam : + ('arg * end_of_stack, 'ret * end_of_stack) descr * Script.node + -> ('arg, 'ret) lambda +[@@coq_force_gadt] + +and 'arg typed_contract = 'arg ty * address + +and 'ty ty = + | Unit_t : type_annot option -> unit ty + | Int_t : type_annot option -> z num ty + | Nat_t : type_annot option -> n num ty + | Signature_t : type_annot option -> signature ty + | String_t : type_annot option -> string ty + | Bytes_t : type_annot option -> bytes ty + | Mutez_t : type_annot option -> Tez.t ty + | Key_hash_t : type_annot option -> public_key_hash ty + | Key_t : type_annot option -> public_key ty + | Timestamp_t : type_annot option -> Script_timestamp.t ty + | Address_t : type_annot option -> address ty + | Bool_t : type_annot option -> bool ty + | Pair_t : + ('a ty * field_annot option * var_annot option) + * ('b ty * field_annot option * var_annot option) + * type_annot option + -> ('a, 'b) pair ty + | Union_t : + ('a ty * field_annot option) + * ('b ty * field_annot option) + * type_annot option + -> ('a, 'b) union ty + | Lambda_t : 'arg ty * 'ret ty * type_annot option -> ('arg, 'ret) lambda ty + | Option_t : 'v ty * type_annot option -> 'v option ty + | List_t : 'v ty * type_annot option -> 'v boxed_list ty + | Set_t : 'v comparable_ty * type_annot option -> 'v set ty + | Map_t : 'k comparable_ty * 'v ty * type_annot option -> ('k, 'v) map ty + | Big_map_t : + 'k comparable_ty * 'v ty * type_annot option + -> ('k, 'v) big_map ty + | Contract_t : 'arg ty * type_annot option -> 'arg typed_contract ty + | Sapling_transaction_t : + Sapling.Memo_size.t * type_annot option + -> Sapling.transaction ty + | Sapling_state_t : + Sapling.Memo_size.t * type_annot option + -> Sapling.state ty + | Operation_t : type_annot option -> operation ty + | Chain_id_t : type_annot option -> Chain_id.t ty + | Never_t : type_annot option -> never ty + | Bls12_381_g1_t : type_annot option -> Bls12_381.G1.t ty + | Bls12_381_g2_t : type_annot option -> Bls12_381.G2.t ty + | Bls12_381_fr_t : type_annot option -> Bls12_381.Fr.t ty + | Ticket_t : 'a comparable_ty * type_annot option -> 'a ticket ty + +and 'ty stack_ty = + | Item_t : + 'ty ty * 'rest stack_ty * var_annot option + -> ('ty * 'rest) stack_ty + | Empty_t : end_of_stack stack_ty + +and ('key, 'value) big_map = { + id : Big_map.Id.t option; + diff : ('key, 'value) big_map_overlay; + key_type : 'key comparable_ty; + value_type : 'value ty; +} + +and 'elt boxed_list = {elements : 'elt list; length : int} + +(* ---- Instructions --------------------------------------------------------*) + +(* The low-level, typed instructions, as a GADT whose parameters + encode the typing rules. + + The left parameter is the typed shape of the stack before the + instruction, the right one the shape after. Any program whose + construction is accepted by OCaml's type-checker is guaranteed to + be type-safe. Overloadings of the concrete syntax are already + resolved in this representation, either by using different + constructors or type witness parameters. + + When adding a new instruction, please check whether it is duplicating a data + (rule of thumb: the type variable appears twice in the after stack, beware + it might be hidden in a witness). + If it is, please protect it with [check_dupable_ty]. +*) +and ('bef, 'aft) instr = + (* stack ops *) + | Drop : (_ * 'rest, 'rest) instr + | Dup : ('top * 'rest, 'top * ('top * 'rest)) instr + | Swap : ('tip * ('top * 'rest), 'top * ('tip * 'rest)) instr + | Const : 'ty -> ('rest, 'ty * 'rest) instr + (* pairs *) + | Cons_pair : ('car * ('cdr * 'rest), ('car, 'cdr) pair * 'rest) instr + | Car : (('car, _) pair * 'rest, 'car * 'rest) instr + | Cdr : ((_, 'cdr) pair * 'rest, 'cdr * 'rest) instr + | Unpair : (('car, 'cdr) pair * 'rest, 'car * ('cdr * 'rest)) instr + (* options *) + | Cons_some : ('v * 'rest, 'v option * 'rest) instr + | Cons_none : 'a ty -> ('rest, 'a option * 'rest) instr + | If_none : + ('bef, 'aft) descr * ('a * 'bef, 'aft) descr + -> ('a option * 'bef, 'aft) instr + (* unions *) + | Cons_left : ('l * 'rest, ('l, 'r) union * 'rest) instr + | Cons_right : ('r * 'rest, ('l, 'r) union * 'rest) instr + | If_left : + ('l * 'bef, 'aft) descr * ('r * 'bef, 'aft) descr + -> (('l, 'r) union * 'bef, 'aft) instr + (* lists *) + | Cons_list : ('a * ('a boxed_list * 'rest), 'a boxed_list * 'rest) instr + | Nil : ('rest, 'a boxed_list * 'rest) instr + | If_cons : + ('a * ('a boxed_list * 'bef), 'aft) descr * ('bef, 'aft) descr + -> ('a boxed_list * 'bef, 'aft) instr + | List_map : + ('a * 'rest, 'b * 'rest) descr + -> ('a boxed_list * 'rest, 'b boxed_list * 'rest) instr + | List_iter : + ('a * 'rest, 'rest) descr + -> ('a boxed_list * 'rest, 'rest) instr + | List_size : ('a boxed_list * 'rest, n num * 'rest) instr + (* sets *) + | Empty_set : 'a comparable_ty -> ('rest, 'a set * 'rest) instr + | Set_iter : ('a * 'rest, 'rest) descr -> ('a set * 'rest, 'rest) instr + | Set_mem : ('elt * ('elt set * 'rest), bool * 'rest) instr + | Set_update : ('elt * (bool * ('elt set * 'rest)), 'elt set * 'rest) instr + | Set_size : ('a set * 'rest, n num * 'rest) instr + (* maps *) + | Empty_map : 'a comparable_ty * 'v ty -> ('rest, ('a, 'v) map * 'rest) instr + | Map_map : + (('a * 'v) * 'rest, 'r * 'rest) descr + -> (('a, 'v) map * 'rest, ('a, 'r) map * 'rest) instr + | Map_iter : + (('a * 'v) * 'rest, 'rest) descr + -> (('a, 'v) map * 'rest, 'rest) instr + | Map_mem : ('a * (('a, 'v) map * 'rest), bool * 'rest) instr + | Map_get : ('a * (('a, 'v) map * 'rest), 'v option * 'rest) instr + | Map_update + : ('a * ('v option * (('a, 'v) map * 'rest)), ('a, 'v) map * 'rest) instr + | Map_get_and_update + : ( 'a * ('v option * (('a, 'v) map * 'rest)), + 'v option * (('a, 'v) map * 'rest) ) + instr + | Map_size : (('a, 'b) map * 'rest, n num * 'rest) instr + (* big maps *) + | Empty_big_map : + 'a comparable_ty * 'v ty + -> ('rest, ('a, 'v) big_map * 'rest) instr + | Big_map_mem : ('a * (('a, 'v) big_map * 'rest), bool * 'rest) instr + | Big_map_get : ('a * (('a, 'v) big_map * 'rest), 'v option * 'rest) instr + | Big_map_update + : ( 'key * ('value option * (('key, 'value) big_map * 'rest)), + ('key, 'value) big_map * 'rest ) + instr + | Big_map_get_and_update + : ( 'a * ('v option * (('a, 'v) big_map * 'rest)), + 'v option * (('a, 'v) big_map * 'rest) ) + instr + (* string operations *) + | Concat_string : (string boxed_list * 'rest, string * 'rest) instr + | Concat_string_pair : (string * (string * 'rest), string * 'rest) instr + | Slice_string + : (n num * (n num * (string * 'rest)), string option * 'rest) instr + | String_size : (string * 'rest, n num * 'rest) instr + (* bytes operations *) + | Concat_bytes : (bytes boxed_list * 'rest, bytes * 'rest) instr + | Concat_bytes_pair : (bytes * (bytes * 'rest), bytes * 'rest) instr + | Slice_bytes + : (n num * (n num * (bytes * 'rest)), bytes option * 'rest) instr + | Bytes_size : (bytes * 'rest, n num * 'rest) instr + (* timestamp operations *) + | Add_seconds_to_timestamp + : ( z num * (Script_timestamp.t * 'rest), + Script_timestamp.t * 'rest ) + instr + | Add_timestamp_to_seconds + : ( Script_timestamp.t * (z num * 'rest), + Script_timestamp.t * 'rest ) + instr + | Sub_timestamp_seconds + : ( Script_timestamp.t * (z num * 'rest), + Script_timestamp.t * 'rest ) + instr + | Diff_timestamps + : ( Script_timestamp.t * (Script_timestamp.t * 'rest), + z num * 'rest ) + instr + (* tez operations *) + | Add_tez : (Tez.t * (Tez.t * 'rest), Tez.t * 'rest) instr + | Sub_tez : (Tez.t * (Tez.t * 'rest), Tez.t * 'rest) instr + | Mul_teznat : (Tez.t * (n num * 'rest), Tez.t * 'rest) instr + | Mul_nattez : (n num * (Tez.t * 'rest), Tez.t * 'rest) instr + | Ediv_teznat + : (Tez.t * (n num * 'rest), (Tez.t, Tez.t) pair option * 'rest) instr + | Ediv_tez + : (Tez.t * (Tez.t * 'rest), (n num, Tez.t) pair option * 'rest) instr + (* boolean operations *) + | Or : (bool * (bool * 'rest), bool * 'rest) instr + | And : (bool * (bool * 'rest), bool * 'rest) instr + | Xor : (bool * (bool * 'rest), bool * 'rest) instr + | Not : (bool * 'rest, bool * 'rest) instr + (* integer operations *) + | Is_nat : (z num * 'rest, n num option * 'rest) instr + | Neg_nat : (n num * 'rest, z num * 'rest) instr + | Neg_int : (z num * 'rest, z num * 'rest) instr + | Abs_int : (z num * 'rest, n num * 'rest) instr + | Int_nat : (n num * 'rest, z num * 'rest) instr + | Add_intint : (z num * (z num * 'rest), z num * 'rest) instr + | Add_intnat : (z num * (n num * 'rest), z num * 'rest) instr + | Add_natint : (n num * (z num * 'rest), z num * 'rest) instr + | Add_natnat : (n num * (n num * 'rest), n num * 'rest) instr + | Sub_int : ('s num * ('t num * 'rest), z num * 'rest) instr + | Mul_intint : (z num * (z num * 'rest), z num * 'rest) instr + | Mul_intnat : (z num * (n num * 'rest), z num * 'rest) instr + | Mul_natint : (n num * (z num * 'rest), z num * 'rest) instr + | Mul_natnat : (n num * (n num * 'rest), n num * 'rest) instr + | Ediv_intint + : (z num * (z num * 'rest), (z num, n num) pair option * 'rest) instr + | Ediv_intnat + : (z num * (n num * 'rest), (z num, n num) pair option * 'rest) instr + | Ediv_natint + : (n num * (z num * 'rest), (z num, n num) pair option * 'rest) instr + | Ediv_natnat + : (n num * (n num * 'rest), (n num, n num) pair option * 'rest) instr + | Lsl_nat : (n num * (n num * 'rest), n num * 'rest) instr + | Lsr_nat : (n num * (n num * 'rest), n num * 'rest) instr + | Or_nat : (n num * (n num * 'rest), n num * 'rest) instr + | And_nat : (n num * (n num * 'rest), n num * 'rest) instr + | And_int_nat : (z num * (n num * 'rest), n num * 'rest) instr + | Xor_nat : (n num * (n num * 'rest), n num * 'rest) instr + | Not_nat : (n num * 'rest, z num * 'rest) instr + | Not_int : (z num * 'rest, z num * 'rest) instr + (* control *) + | Seq : ('bef, 'trans) descr * ('trans, 'aft) descr -> ('bef, 'aft) instr + | If : ('bef, 'aft) descr * ('bef, 'aft) descr -> (bool * 'bef, 'aft) instr + | Loop : ('rest, bool * 'rest) descr -> (bool * 'rest, 'rest) instr + | Loop_left : + ('a * 'rest, ('a, 'b) union * 'rest) descr + -> (('a, 'b) union * 'rest, 'b * 'rest) instr + | Dip : ('bef, 'aft) descr -> ('top * 'bef, 'top * 'aft) instr + | Exec : ('arg * (('arg, 'ret) lambda * 'rest), 'ret * 'rest) instr + | Apply : + 'arg ty + -> ( 'arg * (('arg * 'remaining, 'ret) lambda * 'rest), + ('remaining, 'ret) lambda * 'rest ) + instr + | Lambda : ('arg, 'ret) lambda -> ('rest, ('arg, 'ret) lambda * 'rest) instr + | Failwith : 'a ty -> ('a * 'rest, 'aft) instr + | Nop : ('rest, 'rest) instr + (* comparison *) + | Compare : 'a comparable_ty -> ('a * ('a * 'rest), z num * 'rest) instr + (* comparators *) + | Eq : (z num * 'rest, bool * 'rest) instr + | Neq : (z num * 'rest, bool * 'rest) instr + | Lt : (z num * 'rest, bool * 'rest) instr + | Gt : (z num * 'rest, bool * 'rest) instr + | Le : (z num * 'rest, bool * 'rest) instr + | Ge : (z num * 'rest, bool * 'rest) instr + (* protocol *) + | Address : (_ typed_contract * 'rest, address * 'rest) instr + | Contract : + 'p ty * string + -> (address * 'rest, 'p typed_contract option * 'rest) instr + | Transfer_tokens + : ( 'arg * (Tez.t * ('arg typed_contract * 'rest)), + operation * 'rest ) + instr + | Implicit_account + : (public_key_hash * 'rest, unit typed_contract * 'rest) instr + | Create_contract : + 'g ty + * 'p ty + * ('p * 'g, operation boxed_list * 'g) lambda + * field_annot option + -> ( public_key_hash option * (Tez.t * ('g * 'rest)), + operation * (address * 'rest) ) + instr + | Set_delegate : (public_key_hash option * 'rest, operation * 'rest) instr + | Now : ('rest, Script_timestamp.t * 'rest) instr + | Balance : ('rest, Tez.t * 'rest) instr + | Level : ('rest, n num * 'rest) instr + | Check_signature + : (public_key * (signature * (bytes * 'rest)), bool * 'rest) instr + | Hash_key : (public_key * 'rest, public_key_hash * 'rest) instr + | Pack : 'a ty -> ('a * 'rest, bytes * 'rest) instr + | Unpack : 'a ty -> (bytes * 'rest, 'a option * 'rest) instr + | Blake2b : (bytes * 'rest, bytes * 'rest) instr + | Sha256 : (bytes * 'rest, bytes * 'rest) instr + | Sha512 : (bytes * 'rest, bytes * 'rest) instr + | Source : ('rest, address * 'rest) instr + | Sender : ('rest, address * 'rest) instr + | Self : 'p ty * string -> ('rest, 'p typed_contract * 'rest) instr + | Self_address : ('rest, address * 'rest) instr + | Amount : ('rest, Tez.t * 'rest) instr + | Sapling_empty_state : { + memo_size : Sapling.Memo_size.t; + } + -> ('rest, Sapling.state * 'rest) instr + | Sapling_verify_update + : ( Sapling.transaction * (Sapling.state * 'rest), + (z num, Sapling.state) pair option * 'rest ) + instr + | Dig : + int * ('x * 'rest, 'rest, 'bef, 'aft) stack_prefix_preservation_witness + -> ('bef, 'x * 'aft) instr + | Dug : + int * ('rest, 'x * 'rest, 'bef, 'aft) stack_prefix_preservation_witness + -> ('x * 'bef, 'aft) instr + | Dipn : + int + * ('fbef, 'faft, 'bef, 'aft) stack_prefix_preservation_witness + * ('fbef, 'faft) descr + -> ('bef, 'aft) instr + | Dropn : + int * ('rest, 'rest, 'bef, _) stack_prefix_preservation_witness + -> ('bef, 'rest) instr + | ChainId : ('rest, Chain_id.t * 'rest) instr + | Never : (never * 'rest, 'aft) instr + | Voting_power : (public_key_hash * 'rest, n num * 'rest) instr + | Total_voting_power : ('rest, n num * 'rest) instr + | Keccak : (bytes * 'rest, bytes * 'rest) instr + | Sha3 : (bytes * 'rest, bytes * 'rest) instr + | Add_bls12_381_g1 + : ( Bls12_381.G1.t * (Bls12_381.G1.t * 'rest), + Bls12_381.G1.t * 'rest ) + instr + | Add_bls12_381_g2 + : ( Bls12_381.G2.t * (Bls12_381.G2.t * 'rest), + Bls12_381.G2.t * 'rest ) + instr + | Add_bls12_381_fr + : ( Bls12_381.Fr.t * (Bls12_381.Fr.t * 'rest), + Bls12_381.Fr.t * 'rest ) + instr + | Mul_bls12_381_g1 + : ( Bls12_381.G1.t * (Bls12_381.Fr.t * 'rest), + Bls12_381.G1.t * 'rest ) + instr + | Mul_bls12_381_g2 + : ( Bls12_381.G2.t * (Bls12_381.Fr.t * 'rest), + Bls12_381.G2.t * 'rest ) + instr + | Mul_bls12_381_fr + : ( Bls12_381.Fr.t * (Bls12_381.Fr.t * 'rest), + Bls12_381.Fr.t * 'rest ) + instr + | Mul_bls12_381_z_fr + : (Bls12_381.Fr.t * (_ num * 'rest), Bls12_381.Fr.t * 'rest) instr + | Mul_bls12_381_fr_z + : (_ num * (Bls12_381.Fr.t * 'rest), Bls12_381.Fr.t * 'rest) instr + | Int_bls12_381_fr : (Bls12_381.Fr.t * 'rest, z num * 'rest) instr + | Neg_bls12_381_g1 : (Bls12_381.G1.t * 'rest, Bls12_381.G1.t * 'rest) instr + | Neg_bls12_381_g2 : (Bls12_381.G2.t * 'rest, Bls12_381.G2.t * 'rest) instr + | Neg_bls12_381_fr : (Bls12_381.Fr.t * 'rest, Bls12_381.Fr.t * 'rest) instr + | Pairing_check_bls12_381 + : ( (Bls12_381.G1.t, Bls12_381.G2.t) pair boxed_list * 'rest, + bool * 'rest ) + instr + | Comb : int * ('before, 'after) comb_gadt_witness -> ('before, 'after) instr + | Uncomb : + int * ('before, 'after) uncomb_gadt_witness + -> ('before, 'after) instr + | Comb_get : + int * ('before, 'after) comb_get_gadt_witness + -> ('before * 'rest, 'after * 'rest) instr + | Comb_set : + int * ('value, 'before, 'after) comb_set_gadt_witness + -> ('value * ('before * 'rest), 'after * 'rest) instr + | Dup_n : + int * ('before, 'after) dup_n_gadt_witness + -> ('before, 'after * 'before) instr + | Ticket : ('a * (n num * 'rest), 'a ticket * 'rest) instr + | Read_ticket + : ( 'a ticket * 'rest, + (address * ('a * n num)) * ('a ticket * 'rest) ) + instr + | Split_ticket + : ( 'a ticket * ((n num * n num) * 'rest), + ('a ticket * 'a ticket) option * 'rest ) + instr + | Join_tickets : + 'a comparable_ty + -> (('a ticket * 'a ticket) * 'rest, 'a ticket option * 'rest) instr + +and ('before, 'after) comb_gadt_witness = + | Comb_one : ('a * 'before, 'a * 'before) comb_gadt_witness + | Comb_succ : + ('before, 'b * 'after) comb_gadt_witness + -> ('a * 'before, ('a * 'b) * 'after) comb_gadt_witness + +and ('before, 'after) uncomb_gadt_witness = + | Uncomb_one : ('rest, 'rest) uncomb_gadt_witness + | Uncomb_succ : + ('b * 'before, 'after) uncomb_gadt_witness + -> (('a * 'b) * 'before, 'a * 'after) uncomb_gadt_witness + +and ('before, 'after) comb_get_gadt_witness = + | Comb_get_zero : ('b, 'b) comb_get_gadt_witness + | Comb_get_one : ('a * 'b, 'a) comb_get_gadt_witness + | Comb_get_plus_two : + ('before, 'after) comb_get_gadt_witness + -> ('a * 'before, 'after) comb_get_gadt_witness + +and ('value, 'before, 'after) comb_set_gadt_witness = + | Comb_set_zero : ('value, _, 'value) comb_set_gadt_witness + | Comb_set_one : ('value, 'hd * 'tl, 'value * 'tl) comb_set_gadt_witness + | Comb_set_plus_two : + ('value, 'before, 'after) comb_set_gadt_witness + -> ('value, 'a * 'before, 'a * 'after) comb_set_gadt_witness + +and ('before, 'after) dup_n_gadt_witness = + | Dup_n_zero : ('a * 'rest, 'a) dup_n_gadt_witness + | Dup_n_succ : + ('before, 'b) dup_n_gadt_witness + -> ('a * 'before, 'b) dup_n_gadt_witness + +(* Type witness for operations that work deep in the stack ignoring + (and preserving) a prefix. + + The two right parameters are the shape of the stack with the (same) + prefix before and after the transformation. The two left + parameters are the shape of the stack without the prefix before and + after. The inductive definition makes it so by construction. *) +and ('bef, 'aft, 'bef_suffix, 'aft_suffix) stack_prefix_preservation_witness = + | Prefix : + ('fbef, 'faft, 'bef, 'aft) stack_prefix_preservation_witness + -> ('fbef, 'faft, 'x * 'bef, 'x * 'aft) stack_prefix_preservation_witness + | Rest : ('bef, 'aft, 'bef, 'aft) stack_prefix_preservation_witness + +and ('bef, 'aft) descr = { + loc : Script.location; + bef : 'bef stack_ty; + aft : 'aft stack_ty; + instr : ('bef, 'aft) instr; +} diff --git a/src/proto_009_PsFLoren/lib_protocol/seed_repr.ml b/src/proto_009_PsFLoren/lib_protocol/seed_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..591f7da797a9a07380cc201c8ad5420e250f1809 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/seed_repr.ml @@ -0,0 +1,134 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Random number generation *) + +type seed = B of State_hash.t + +type t = T of State_hash.t + +type sequence = S of State_hash.t + +type nonce = bytes + +let nonce_encoding = Data_encoding.Fixed.bytes Constants_repr.nonce_length + +let initial_seed = "Laissez-faire les proprietaires." + +let zero_bytes = Bytes.make Nonce_hash.size '\000' + +let state_hash_encoding = + let open Data_encoding in + conv + State_hash.to_bytes + State_hash.of_bytes_exn + (Fixed.bytes Nonce_hash.size) + +let seed_encoding = + let open Data_encoding in + conv (fun (B b) -> b) (fun b -> B b) state_hash_encoding + +let empty = B (State_hash.hash_bytes [Bytes.of_string initial_seed]) + +let nonce (B state) nonce = + B (State_hash.hash_bytes [State_hash.to_bytes state; nonce]) + +let initialize_new (B state) append = + T (State_hash.hash_bytes (State_hash.to_bytes state :: zero_bytes :: append)) + +let xor_higher_bits i b = + let higher = TzEndian.get_int32 b 0 in + let r = Int32.logxor higher i in + let res = Bytes.copy b in + TzEndian.set_int32 res 0 r ; res + +let sequence (T state) n = + State_hash.to_bytes state |> xor_higher_bits n + |> fun b -> S (State_hash.hash_bytes [b]) + +let take (S state) = + let b = State_hash.to_bytes state in + let h = State_hash.hash_bytes [b] in + (State_hash.to_bytes h, S h) + +let take_int32 s bound = + if Compare.Int32.(bound <= 0l) then invalid_arg "Seed_repr.take_int32" + (* FIXME *) + else + let rec loop s = + let (bytes, s) = take s in + let r = Int32.abs (TzEndian.get_int32 bytes 0) in + let drop_if_over = + Int32.sub Int32.max_int (Int32.rem Int32.max_int bound) + in + if Compare.Int32.(r >= drop_if_over) then loop s + else + let v = Int32.rem r bound in + (v, s) + in + loop s + +type error += Unexpected_nonce_length (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"unexpected_nonce_length" + ~title:"Unexpected nonce length" + ~description:"Nonce length is incorrect." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Nonce length is not %i bytes long as it should." + Constants_repr.nonce_length) + Data_encoding.empty + (function Unexpected_nonce_length -> Some () | _ -> None) + (fun () -> Unexpected_nonce_length) + +let make_nonce nonce = + if Compare.Int.(Bytes.length nonce <> Constants_repr.nonce_length) then + error Unexpected_nonce_length + else ok nonce + +let hash nonce = Nonce_hash.hash_bytes [nonce] + +let check_hash nonce hash = + Compare.Int.(Bytes.length nonce = Constants_repr.nonce_length) + && Nonce_hash.equal (Nonce_hash.hash_bytes [nonce]) hash + +let nonce_hash_key_part = Nonce_hash.to_path + +let initial_nonce_0 = zero_bytes + +let initial_nonce_hash_0 = hash initial_nonce_0 + +let deterministic_seed seed = nonce seed zero_bytes + +let initial_seeds n = + let rec loop acc elt i = + if Compare.Int.(i = 1) then List.rev (elt :: acc) + else loop (elt :: acc) (deterministic_seed elt) (i - 1) + in + loop [] (B (State_hash.hash_bytes [])) n diff --git a/src/proto_009_PsFLoren/lib_protocol/seed_repr.mli b/src/proto_009_PsFLoren/lib_protocol/seed_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..a067ac9d2952b9a351f26319d436ec733b2fa110 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/seed_repr.mli @@ -0,0 +1,100 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Random number generation + + This is not expected to be a good cryptographic random number + generator. In particular this is supposed to be used in situations + where the seed is a globally known information. + + The only expected property is: It should be difficult to find a + seed such that the generated sequence is a given one. *) + +(** {2 Random Generation} *) + +(** The state of the random number generator *) +type t + +(** A random seed, to derive random sequences from *) +type seed + +(** A random sequence, to derive random values from *) +type sequence + +(** [initialize_new state ident] returns a new generator *) +val initialize_new : seed -> bytes list -> t + +(** [sequence state n] prepares the n-th sequence of a state *) +val sequence : t -> int32 -> sequence + +(** Generates the next random value in the sequence *) +val take : sequence -> bytes * sequence + +(** Generates the next random value as a bounded [int32] *) +val take_int32 : sequence -> int32 -> int32 * sequence + +(** {2 Predefined seeds} *) + +val empty : seed + +(** Returns a new seed by hashing the one passed with a constant. *) +val deterministic_seed : seed -> seed + +(** [initial_seeds n] generates the first [n] seeds for which there are no nonces. + The first seed is a constant value. The kth seed is the hash of seed (k-1) + concatenated with a constant. *) +val initial_seeds : int -> seed list + +(** {2 Entropy} *) + +(** A nonce for adding entropy to the generator *) +type nonce + +(** Add entropy to the seed generator *) +val nonce : seed -> nonce -> seed + +(** Use a byte sequence as a nonce *) +val make_nonce : bytes -> nonce tzresult + +(** Compute the has of a nonce *) +val hash : nonce -> Nonce_hash.t + +(** [check_hash nonce hash] is true if the nonce correspond to the hash *) +val check_hash : nonce -> Nonce_hash.t -> bool + +(** For using nonce hashes as keys in the hierarchical database *) +val nonce_hash_key_part : Nonce_hash.t -> string list -> string list + +(** {2 Predefined nonce} *) + +val initial_nonce_0 : nonce + +val initial_nonce_hash_0 : Nonce_hash.t + +(** {2 Serializers} *) + +val nonce_encoding : nonce Data_encoding.t + +val seed_encoding : seed Data_encoding.t diff --git a/src/proto_009_PsFLoren/lib_protocol/seed_storage.ml b/src/proto_009_PsFLoren/lib_protocol/seed_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..67bba15066112d38e70ca3a59b2434355c642dbb --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/seed_storage.ml @@ -0,0 +1,146 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Misc + +type error += + | Unknown of { + oldest : Cycle_repr.t; + cycle : Cycle_repr.t; + latest : Cycle_repr.t; + } + +(* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"seed.unknown_seed" + ~title:"Unknown seed" + ~description:"The requested seed is not available" + ~pp:(fun ppf (oldest, cycle, latest) -> + if Cycle_repr.(cycle < oldest) then + Format.fprintf + ppf + "The seed for cycle %a has been cleared from the context (oldest \ + known seed is for cycle %a)" + Cycle_repr.pp + cycle + Cycle_repr.pp + oldest + else + Format.fprintf + ppf + "The seed for cycle %a has not been computed yet (latest known \ + seed is for cycle %a)" + Cycle_repr.pp + cycle + Cycle_repr.pp + latest) + Data_encoding.( + obj3 + (req "oldest" Cycle_repr.encoding) + (req "requested" Cycle_repr.encoding) + (req "latest" Cycle_repr.encoding)) + (function + | Unknown {oldest; cycle; latest} -> + Some (oldest, cycle, latest) + | _ -> + None) + (fun (oldest, cycle, latest) -> Unknown {oldest; cycle; latest}) + +let compute_for_cycle c ~revealed cycle = + match Cycle_repr.pred cycle with + | None -> + assert false (* should not happen *) + | Some previous_cycle -> + let levels = Level_storage.levels_with_commitments_in_cycle c revealed in + let combine (c, random_seed, unrevealed) level = + Storage.Seed.Nonce.get c level + >>=? function + | Revealed nonce -> + Storage.Seed.Nonce.remove_existing c level + >|=? fun c -> (c, Seed_repr.nonce random_seed nonce, unrevealed) + | Unrevealed u -> + Storage.Seed.Nonce.remove_existing c level + >|=? fun c -> (c, random_seed, u :: unrevealed) + in + Storage.Seed.For_cycle.get c previous_cycle + >>=? fun prev_seed -> + let seed = Seed_repr.deterministic_seed prev_seed in + fold_left_s combine (c, seed, []) levels + >>=? fun (c, seed, unrevealed) -> + Storage.Seed.For_cycle.init c cycle seed >|=? fun c -> (c, unrevealed) + +let for_cycle ctxt cycle = + let preserved = Constants_storage.preserved_cycles ctxt in + let current_level = Level_storage.current ctxt in + let current_cycle = current_level.cycle in + let latest = + if Cycle_repr.(current_cycle = root) then + Cycle_repr.add current_cycle (preserved + 1) + else Cycle_repr.add current_cycle preserved + in + let oldest = + match Cycle_repr.sub current_cycle preserved with + | None -> + Cycle_repr.root + | Some oldest -> + oldest + in + error_unless + Cycle_repr.(oldest <= cycle && cycle <= latest) + (Unknown {oldest; cycle; latest}) + >>?= fun () -> Storage.Seed.For_cycle.get ctxt cycle + +let clear_cycle c cycle = Storage.Seed.For_cycle.remove_existing c cycle + +let init ctxt = + let preserved = Constants_storage.preserved_cycles ctxt in + List.fold_left2 + (fun ctxt c seed -> + ctxt + >>=? fun ctxt -> + let cycle = Cycle_repr.of_int32_exn (Int32.of_int c) in + Storage.Seed.For_cycle.init ctxt cycle seed) + (return ctxt) + (0 --> (preserved + 1)) + (Seed_repr.initial_seeds (preserved + 2)) + +let cycle_end ctxt last_cycle = + let preserved = Constants_storage.preserved_cycles ctxt in + ( match Cycle_repr.sub last_cycle preserved with + | None -> + return ctxt + | Some cleared_cycle -> + clear_cycle ctxt cleared_cycle ) + >>=? fun ctxt -> + match Cycle_repr.pred last_cycle with + | None -> + return (ctxt, []) + | Some revealed -> + (* cycle with revelations *) + let inited_seed_cycle = Cycle_repr.add last_cycle (preserved + 1) in + compute_for_cycle ctxt ~revealed inited_seed_cycle diff --git a/src/proto_009_PsFLoren/lib_protocol/seed_storage.mli b/src/proto_009_PsFLoren/lib_protocol/seed_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..37e87efed99be2323d767f15a3dda6f117baff00 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/seed_storage.mli @@ -0,0 +1,47 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Unknown of { + oldest : Cycle_repr.t; + cycle : Cycle_repr.t; + latest : Cycle_repr.t; + } + +(* `Permanent *) + +(** Generates the first [preserved_cycles+2] seeds for which + there are no nonces. *) +val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + +val for_cycle : Raw_context.t -> Cycle_repr.t -> Seed_repr.seed tzresult Lwt.t + +(** If it is the end of the cycle, computes and stores the seed of cycle at + distance [preserved_cycle+2] in the future using the seed of the previous + cycle and the revelations of the current one. *) +val cycle_end : + Raw_context.t -> + Cycle_repr.t -> + (Raw_context.t * Nonce_storage.unrevealed list) tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/services_registration.ml b/src/proto_009_PsFLoren/lib_protocol/services_registration.ml new file mode 100644 index 0000000000000000000000000000000000000000..c887bb09f4c1395258c20665c636640f0e16ff7f --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/services_registration.ml @@ -0,0 +1,84 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type rpc_context = { + block_hash : Block_hash.t; + block_header : Block_header.shell_header; + context : Alpha_context.t; +} + +let rpc_init ({block_hash; block_header; context} : Updater.rpc_context) = + let level = block_header.level in + let timestamp = block_header.timestamp in + let fitness = block_header.fitness in + Alpha_context.prepare + ~level + ~predecessor_timestamp:timestamp + ~timestamp + ~fitness + context + >|=? fun (context, _balance_updates) -> {block_hash; block_header; context} + +let rpc_services = + ref (RPC_directory.empty : Updater.rpc_context RPC_directory.t) + +let register0_fullctxt s f = + rpc_services := + RPC_directory.register !rpc_services s (fun ctxt q i -> + rpc_init ctxt >>=? fun ctxt -> f ctxt q i) + +let register0 s f = register0_fullctxt s (fun {context; _} -> f context) + +let register0_noctxt s f = + rpc_services := RPC_directory.register !rpc_services s (fun _ q i -> f q i) + +let register1_fullctxt s f = + rpc_services := + RPC_directory.register !rpc_services s (fun (ctxt, arg) q i -> + rpc_init ctxt >>=? fun ctxt -> f ctxt arg q i) + +let register1 s f = register1_fullctxt s (fun {context; _} x -> f context x) + +let register2_fullctxt s f = + rpc_services := + RPC_directory.register !rpc_services s (fun ((ctxt, arg1), arg2) q i -> + rpc_init ctxt >>=? fun ctxt -> f ctxt arg1 arg2 q i) + +let register2 s f = + register2_fullctxt s (fun {context; _} a1 a2 q i -> f context a1 a2 q i) + +let get_rpc_services () = + let p = + RPC_directory.map + (fun c -> + rpc_init c >|= function Error _ -> assert false | Ok c -> c.context) + (Storage_description.build_directory Alpha_context.description) + in + RPC_directory.register_dynamic_directory + !rpc_services + RPC_path.(open_root / "context" / "raw" / "json") + (fun _ -> Lwt.return p) diff --git a/src/proto_009_PsFLoren/lib_protocol/services_registration.mli b/src/proto_009_PsFLoren/lib_protocol/services_registration.mli new file mode 100644 index 0000000000000000000000000000000000000000..58fb1053daf7fd11868c3245d2d4cc467df28c9c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/services_registration.mli @@ -0,0 +1,102 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type rpc_context = { + block_hash : Block_hash.t; + block_header : Block_header.shell_header; + context : t; +} + +val rpc_init : Updater.rpc_context -> (rpc_context, error trace) result Lwt.t + +val register0 : + ( [< RPC_service.meth], + Updater.rpc_context, + Updater.rpc_context, + 'a, + 'b, + 'c ) + RPC_service.t -> + (t -> + 'a -> + 'b -> + ('c, Error_monad.error Error_monad.trace) Pervasives.result Lwt.t) -> + unit + +val register0_noctxt : + ([< RPC_service.meth], Updater.rpc_context, 'a, 'b, 'c, 'd) RPC_service.t -> + ('b -> 'c -> 'd Error_monad.tzresult Lwt.t) -> + unit + +val register1_fullctxt : + ( [< RPC_service.meth], + Updater.rpc_context, + Updater.rpc_context * 'a, + 'b, + 'c, + 'd ) + RPC_service.t -> + (rpc_context -> + 'a -> + 'b -> + 'c -> + ('d, Error_monad.error Error_monad.trace) Pervasives.result Lwt.t) -> + unit + +val register1 : + ( [< RPC_service.meth], + Updater.rpc_context, + Updater.rpc_context * 'a, + 'b, + 'c, + 'd ) + RPC_service.t -> + (t -> + 'a -> + 'b -> + 'c -> + ('d, Error_monad.error Error_monad.trace) Pervasives.result Lwt.t) -> + unit + +val register2 : + ( [< RPC_service.meth], + Updater.rpc_context, + (Updater.rpc_context * 'a) * 'b, + 'c, + 'd, + 'e ) + RPC_service.t -> + (t -> + 'a -> + 'b -> + 'c -> + 'd -> + ('e, Error_monad.error Error_monad.trace) Pervasives.result Lwt.t) -> + unit + +val get_rpc_services : unit -> Updater.rpc_context RPC_directory.directory diff --git a/src/proto_009_PsFLoren/lib_protocol/state_hash.ml b/src/proto_009_PsFLoren/lib_protocol/state_hash.ml new file mode 100644 index 0000000000000000000000000000000000000000..f72c0d5c5637638e07207fe0942099c636e29baa --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/state_hash.ml @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let random_state_hash = "\076\064\204" (* rng(53): never used... *) + +include Blake2B.Make + (Base58) + (struct + let name = "random" + + let title = "A random generation state" + + let b58check_prefix = random_state_hash + + let size = None + end) + +let () = Base58.check_encoded_prefix b58check_encoding "rng" 53 diff --git a/src/proto_009_PsFLoren/lib_protocol/state_hash.mli b/src/proto_009_PsFLoren/lib_protocol/state_hash.mli new file mode 100644 index 0000000000000000000000000000000000000000..5e374f2a38c0b0f7da05eaa33e91932d40e49838 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/state_hash.mli @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include S.HASH diff --git a/src/proto_009_PsFLoren/lib_protocol/storage.ml b/src/proto_009_PsFLoren/lib_protocol/storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..6135c28e535aa709630c18cecc51eab7b58e9f52 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/storage.ml @@ -0,0 +1,1229 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Storage_functors + +module UInt16 = struct + type t = int + + let encoding = Data_encoding.uint16 +end + +module Int32 = struct + include Int32 + + let encoding = Data_encoding.int32 +end + +module Int64 = struct + include Int64 + + let encoding = Data_encoding.int64 +end + +module Z = struct + type t = Z.t + + let encoding = Data_encoding.z +end + +module Int31_index : INDEX with type t = int = struct + type t = int + + let path_length = 1 + + let to_path c l = string_of_int c :: l + + let of_path = function + | [] | _ :: _ :: _ -> + None + | [c] -> + int_of_string_opt c + + type 'a ipath = 'a * t + + let args = + Storage_description.One + { + rpc_arg = RPC_arg.int; + encoding = Data_encoding.int31; + compare = Compare.Int.compare; + } +end + +module Make_index (H : Storage_description.INDEX) : + INDEX with type t = H.t and type 'a ipath = 'a * H.t = struct + include H + + type 'a ipath = 'a * t + + let args = Storage_description.One {rpc_arg; encoding; compare} +end + +module Block_priority = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["block_priority"] + end) + (UInt16) + +(** Contracts handling *) + +module Contract = struct + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["contracts"] + end) + + module Global_counter = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["global_counter"] + end) + (Z) + + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["index"] + end)) + (Make_index (Contract_repr.Index)) + + let fold = Indexed_context.fold_keys + + let list = Indexed_context.keys + + module Balance = + Indexed_context.Make_map + (struct + let name = ["balance"] + end) + (Tez_repr) + + module Frozen_balance_index = + Make_indexed_subcontext + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["frozen_balance"] + end)) + (Make_index (Cycle_repr.Index)) + + module Frozen_deposits = + Frozen_balance_index.Make_map + (struct + let name = ["deposits"] + end) + (Tez_repr) + + module Frozen_fees = + Frozen_balance_index.Make_map + (struct + let name = ["fees"] + end) + (Tez_repr) + + module Frozen_rewards = + Frozen_balance_index.Make_map + (struct + let name = ["rewards"] + end) + (Tez_repr) + + module Manager = + Indexed_context.Make_map + (struct + let name = ["manager"] + end) + (Manager_repr) + + module Delegate = + Indexed_context.Make_map + (struct + let name = ["delegate"] + end) + (Signature.Public_key_hash) + + module Inactive_delegate = + Indexed_context.Make_set + (Registered) + (struct + let name = ["inactive_delegate"] + end) + + module Delegate_desactivation = + Indexed_context.Make_map + (struct + let name = ["delegate_desactivation"] + end) + (Cycle_repr) + + module Delegated = + Make_data_set_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["delegated"] + end)) + (Make_index (Contract_repr.Index)) + + module Counter = + Indexed_context.Make_map + (struct + let name = ["counter"] + end) + (Z) + + (* Consume gas for serialization and deserialization of expr in this + module *) + module Make_carbonated_map_expr (N : Storage_sigs.NAME) : + Storage_sigs.Non_iterable_indexed_carbonated_data_storage + with type key = Contract_repr.t + and type value = Script_repr.lazy_expr + and type t := Raw_context.t = struct + module I = + Indexed_context.Make_carbonated_map + (N) + (struct + type t = Script_repr.lazy_expr + + let encoding = Script_repr.lazy_expr_encoding + end) + + type context = I.context + + type key = I.key + + type value = I.value + + let mem = I.mem + + let remove_existing = I.remove_existing + + let remove = I.remove + + let consume_deserialize_gas ctxt value = + Raw_context.check_enough_gas + ctxt + (Script_repr.minimal_deserialize_cost value) + >>? fun () -> + Script_repr.force_decode value + >>? fun (_value, value_cost) -> Raw_context.consume_gas ctxt value_cost + + let consume_serialize_gas ctxt value = + Script_repr.force_bytes value + >>? fun (_value, value_cost) -> Raw_context.consume_gas ctxt value_cost + + let get ctxt contract = + I.get ctxt contract + >>=? fun (ctxt, value) -> + Lwt.return + (consume_deserialize_gas ctxt value >|? fun ctxt -> (ctxt, value)) + + let find ctxt contract = + I.find ctxt contract + >>=? fun (ctxt, value_opt) -> + Lwt.return + @@ + match value_opt with + | None -> + ok (ctxt, None) + | Some value -> + consume_deserialize_gas ctxt value >|? fun ctxt -> (ctxt, value_opt) + + let update ctxt contract value = + consume_serialize_gas ctxt value + >>?= fun ctxt -> I.update ctxt contract value + + let add_or_remove ctxt contract value_opt = + match value_opt with + | None -> + I.add_or_remove ctxt contract None + | Some value -> + consume_serialize_gas ctxt value + >>?= fun ctxt -> I.add_or_remove ctxt contract value_opt + + let init ctxt contract value = + consume_serialize_gas ctxt value + >>?= fun ctxt -> I.init ctxt contract value + + let add ctxt contract value = + consume_serialize_gas ctxt value + >>?= fun ctxt -> I.add ctxt contract value + end + + module Code = Make_carbonated_map_expr (struct + let name = ["code"] + end) + + module Storage = Make_carbonated_map_expr (struct + let name = ["storage"] + end) + + module Paid_storage_space = + Indexed_context.Make_map + (struct + let name = ["paid_bytes"] + end) + (Z) + + module Used_storage_space = + Indexed_context.Make_map + (struct + let name = ["used_bytes"] + end) + (Z) + + module Roll_list = + Indexed_context.Make_map + (struct + let name = ["roll_list"] + end) + (Roll_repr) + + module Change = + Indexed_context.Make_map + (struct + let name = ["change"] + end) + (Tez_repr) +end + +(** Big maps handling *) + +module Big_map = struct + type id = Lazy_storage_kind.Big_map.Id.t + + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["big_maps"] + end) + + module Next = struct + include Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["next"] + end) + (Lazy_storage_kind.Big_map.Id) + + let incr ctxt = + get ctxt + >>=? fun i -> + update ctxt (Lazy_storage_kind.Big_map.Id.next i) + >|=? fun ctxt -> (ctxt, i) + + let init ctxt = init ctxt Lazy_storage_kind.Big_map.Id.init + end + + module Index = struct + (* After flat storage, just use module Index = Lazy_storage_kind.Big_map.Id *) + + include Lazy_storage_kind.Big_map.Id + + let path_length = 6 + path_length + + let to_path c l = + let raw_key = Data_encoding.Binary.to_bytes_exn encoding c in + let (`Hex index_key) = Hex.of_bytes (Raw_hashes.blake2b raw_key) in + String.sub index_key 0 2 :: String.sub index_key 2 2 + :: String.sub index_key 4 2 :: String.sub index_key 6 2 + :: String.sub index_key 8 2 :: String.sub index_key 10 2 :: to_path c l + + let of_path = function + | [] + | [_] + | [_; _] + | [_; _; _] + | [_; _; _; _] + | [_; _; _; _; _] + | [_; _; _; _; _; _] + | _ :: _ :: _ :: _ :: _ :: _ :: _ :: _ :: _ -> + None + | index1 :: index2 :: index3 :: index4 :: index5 :: index6 :: tail -> + of_path tail + |> Option.map (fun c -> + let raw_key = Data_encoding.Binary.to_bytes_exn encoding c in + let (`Hex index_key) = + Hex.of_bytes (Raw_hashes.blake2b raw_key) + in + assert (Compare.String.(String.sub index_key 0 2 = index1)) ; + assert (Compare.String.(String.sub index_key 2 2 = index2)) ; + assert (Compare.String.(String.sub index_key 4 2 = index3)) ; + assert (Compare.String.(String.sub index_key 6 2 = index4)) ; + assert (Compare.String.(String.sub index_key 8 2 = index5)) ; + assert (Compare.String.(String.sub index_key 10 2 = index6)) ; + c) + end + + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["index"] + end)) + (Make_index (Index)) + + let rpc_arg = Index.rpc_arg + + let fold = Indexed_context.fold_keys + + let list = Indexed_context.keys + + let remove ctxt n = Indexed_context.remove ctxt n + + let copy ctxt ~from ~to_ = Indexed_context.copy ctxt ~from ~to_ + + type key = Raw_context.t * Index.t + + module Total_bytes = + Indexed_context.Make_map + (struct + let name = ["total_bytes"] + end) + (Z) + + module Key_type = + Indexed_context.Make_map + (struct + let name = ["key_type"] + end) + (struct + type t = Script_repr.expr + + let encoding = Script_repr.expr_encoding + end) + + module Value_type = + Indexed_context.Make_map + (struct + let name = ["value_type"] + end) + (struct + type t = Script_repr.expr + + let encoding = Script_repr.expr_encoding + end) + + module Contents = struct + module I = + Storage_functors.Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["contents"] + end)) + (Make_index (Script_expr_hash)) + (struct + type t = Script_repr.expr + + let encoding = Script_repr.expr_encoding + end) + + type context = I.context + + type key = I.key + + type value = I.value + + let mem = I.mem + + let remove_existing = I.remove_existing + + let remove = I.remove + + let update = I.update + + let add_or_remove = I.add_or_remove + + let init = I.init + + let add = I.add + + let consume_deserialize_gas ctxt value = + Raw_context.consume_gas ctxt (Script_repr.deserialized_cost value) + + let get ctxt contract = + I.get ctxt contract + >>=? fun (ctxt, value) -> + Lwt.return + (consume_deserialize_gas ctxt value >|? fun ctxt -> (ctxt, value)) + + let find ctxt contract = + I.find ctxt contract + >>=? fun (ctxt, value_opt) -> + Lwt.return + @@ + match value_opt with + | None -> + ok (ctxt, None) + | Some value -> + consume_deserialize_gas ctxt value >|? fun ctxt -> (ctxt, value_opt) + end +end + +module Sapling = struct + type id = Lazy_storage_kind.Sapling_state.Id.t + + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["sapling"] + end) + + module Next = struct + include Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["next"] + end) + (Lazy_storage_kind.Sapling_state.Id) + + let incr ctxt = + get ctxt + >>=? fun i -> + update ctxt (Lazy_storage_kind.Sapling_state.Id.next i) + >|=? fun ctxt -> (ctxt, i) + + let init ctxt = init ctxt Lazy_storage_kind.Sapling_state.Id.init + end + + module Index = Lazy_storage_kind.Sapling_state.Id + + let rpc_arg = Index.rpc_arg + + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["index"] + end)) + (Make_index (Index)) + + let remove ctxt n = Indexed_context.remove ctxt n + + let copy ctxt ~from ~to_ = Indexed_context.copy ctxt ~from ~to_ + + module Total_bytes = + Indexed_context.Make_map + (struct + let name = ["total_bytes"] + end) + (Z) + + module Commitments_size = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitments_size"] + end) + (Int64) + + module Memo_size = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["memo_size"] + end) + (Sapling_repr.Memo_size) + + module Commitments = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitments"] + end)) + (Make_index (struct + type t = int64 + + let rpc_arg = + let construct = Int64.to_string in + let destruct hash = + match Int64.of_string_opt hash with + | None -> + Error "Cannot parse node position" + | Some id -> + Ok id + in + RPC_arg.make + ~descr:"The position of a node in a sapling commitment tree" + ~name:"sapling_node_position" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "sapling_node_position" + ~title:"Sapling node position" + ~description: + "The position of a node in a sapling commitment tree" + Data_encoding.int64 + + let compare = Compare.Int64.compare + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function [c] -> Int64.of_string_opt c | _ -> None + end)) + (Sapling.Hash) + + let commitments_init ctx id = + Indexed_context.Raw_context.remove (ctx, id) ["commitments"] + >|= fun (ctx, _id) -> ctx + + module Ciphertexts = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["ciphertexts"] + end)) + (Make_index (struct + type t = int64 + + let rpc_arg = + let construct = Int64.to_string in + let destruct hash = + match Int64.of_string_opt hash with + | None -> + Error "Cannot parse ciphertext position" + | Some id -> + Ok id + in + RPC_arg.make + ~descr:"The position of a sapling ciphertext" + ~name:"sapling_ciphertext_position" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "sapling_ciphertext_position" + ~title:"Sapling ciphertext position" + ~description:"The position of a sapling ciphertext" + Data_encoding.int64 + + let compare = Compare.Int64.compare + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function [c] -> Int64.of_string_opt c | _ -> None + end)) + (Sapling.Ciphertext) + + let ciphertexts_init ctx id = + Indexed_context.Raw_context.remove (ctx, id) ["commitments"] + >|= fun (ctx, _id) -> ctx + + module Nullifiers_size = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["nullifiers_size"] + end) + (Int64) + + (* For sequential access when building a diff *) + module Nullifiers_ordered = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["nullifiers_ordered"] + end)) + (Make_index (struct + type t = int64 + + let rpc_arg = + let construct = Int64.to_string in + let destruct hash = + match Int64.of_string_opt hash with + | None -> + Error "Cannot parse nullifier position" + | Some id -> + Ok id + in + RPC_arg.make + ~descr:"A sapling nullifier position" + ~name:"sapling_nullifier_position" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "sapling_nullifier_position" + ~title:"Sapling nullifier position" + ~description:"Sapling nullifier position" + Data_encoding.int64 + + let compare = Compare.Int64.compare + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function [c] -> Int64.of_string_opt c | _ -> None + end)) + (Sapling.Nullifier) + + (* Check membership in O(1) for verify_update *) + module Nullifiers_hashed = + Make_carbonated_data_set_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["nullifiers_hashed"] + end)) + (Make_index (struct + type t = Sapling.Nullifier.t + + let encoding = Sapling.Nullifier.encoding + + let of_string hexstring = + let b = Hex.to_bytes (`Hex hexstring) in + match Data_encoding.Binary.of_bytes encoding b with + | None -> + Error "Cannot parse sapling nullifier" + | Some nf -> + Ok nf + + let to_string nf = + let b = Data_encoding.Binary.to_bytes_exn encoding nf in + let (`Hex hexstring) = Hex.of_bytes b in + hexstring + + let rpc_arg = + RPC_arg.make + ~descr:"A sapling nullifier" + ~name:"sapling_nullifier" + ~construct:to_string + ~destruct:of_string + () + + let compare = Sapling.Nullifier.compare + + let path_length = 1 + + let to_path c l = to_string c :: l + + let of_path = function + | [c] -> ( + match of_string c with Error _ -> None | Ok nf -> Some nf ) + | _ -> + None + end)) + + let nullifiers_init ctx id = + Nullifiers_size.add (ctx, id) Int64.zero + >>= fun ctx -> + Indexed_context.Raw_context.remove (ctx, id) ["nullifiers_ordered"] + >>= fun (ctx, id) -> + Indexed_context.Raw_context.remove (ctx, id) ["nullifiers_hashed"] + >|= fun (ctx, _id) -> ctx + + module Roots = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["roots"] + end)) + (Make_index (struct + type t = int32 + + let rpc_arg = + let construct = Int32.to_string in + let destruct hash = + match Int32.of_string_opt hash with + | None -> + Error "Cannot parse nullifier position" + | Some id -> + Ok id + in + RPC_arg.make + ~descr:"A sapling root" + ~name:"sapling_root" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "sapling_root" + ~title:"Sapling root" + ~description:"Sapling root" + Data_encoding.int32 + + let compare = Compare.Int32.compare + + let path_length = 1 + + let to_path c l = Int32.to_string c :: l + + let of_path = function [c] -> Int32.of_string_opt c | _ -> None + end)) + (Sapling.Hash) + + module Roots_pos = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["roots_pos"] + end) + (Int32) + + module Roots_level = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["roots_level"] + end) + (Raw_level_repr) +end + +module Delegates = + Make_data_set_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["delegates"] + end)) + (Make_index (Signature.Public_key_hash)) + +module Active_delegates_with_rolls = + Make_data_set_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["active_delegates_with_rolls"] + end)) + (Make_index (Signature.Public_key_hash)) + +module Delegates_with_frozen_balance_index = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["delegates_with_frozen_balance"] + end)) + (Make_index (Cycle_repr.Index)) + +module Delegates_with_frozen_balance = + Make_data_set_storage + (Delegates_with_frozen_balance_index.Raw_context) + (Make_index (Signature.Public_key_hash)) + +(** Rolls *) + +module Cycle = struct + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["cycle"] + end)) + (Make_index (Cycle_repr.Index)) + + module Last_roll = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["last_roll"] + end)) + (Int31_index) + (Roll_repr) + + module Roll_snapshot = + Indexed_context.Make_map + (struct + let name = ["roll_snapshot"] + end) + (UInt16) + + type unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; + rewards : Tez_repr.t; + fees : Tez_repr.t; + } + + type nonce_status = + | Unrevealed of unrevealed_nonce + | Revealed of Seed_repr.nonce + + let nonce_status_encoding = + let open Data_encoding in + union + [ case + (Tag 0) + ~title:"Unrevealed" + (tup4 + Nonce_hash.encoding + Signature.Public_key_hash.encoding + Tez_repr.encoding + Tez_repr.encoding) + (function + | Unrevealed {nonce_hash; delegate; rewards; fees} -> + Some (nonce_hash, delegate, rewards, fees) + | _ -> + None) + (fun (nonce_hash, delegate, rewards, fees) -> + Unrevealed {nonce_hash; delegate; rewards; fees}); + case + (Tag 1) + ~title:"Revealed" + Seed_repr.nonce_encoding + (function Revealed nonce -> Some nonce | _ -> None) + (fun nonce -> Revealed nonce) ] + + module Nonce = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["nonces"] + end)) + (Make_index (Raw_level_repr.Index)) + (struct + type t = nonce_status + + let encoding = nonce_status_encoding + end) + + module Seed = + Indexed_context.Make_map + (struct + let name = ["random_seed"] + end) + (struct + type t = Seed_repr.seed + + let encoding = Seed_repr.seed_encoding + end) +end + +module Roll = struct + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["rolls"] + end) + + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["index"] + end)) + (Make_index (Roll_repr.Index)) + + module Next = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["next"] + end) + (Roll_repr) + + module Limbo = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["limbo"] + end) + (Roll_repr) + + module Delegate_roll_list = + Wrap_indexed_data_storage + (Contract.Roll_list) + (struct + type t = Signature.Public_key_hash.t + + let wrap = Contract_repr.implicit_contract + + let unwrap = Contract_repr.is_implicit + end) + + module Successor = + Indexed_context.Make_map + (struct + let name = ["successor"] + end) + (Roll_repr) + + module Delegate_change = + Wrap_indexed_data_storage + (Contract.Change) + (struct + type t = Signature.Public_key_hash.t + + let wrap = Contract_repr.implicit_contract + + let unwrap = Contract_repr.is_implicit + end) + + module Snapshoted_owner_index = struct + type t = Cycle_repr.t * int + + let path_length = Cycle_repr.Index.path_length + 1 + + let to_path (c, n) s = Cycle_repr.Index.to_path c (string_of_int n :: s) + + let of_path l = + match Misc.take Cycle_repr.Index.path_length l with + | None | Some (_, ([] | _ :: _ :: _)) -> + None + | Some (l1, [l2]) -> ( + match (Cycle_repr.Index.of_path l1, int_of_string_opt l2) with + | (None, _) | (_, None) -> + None + | (Some c, Some i) -> + Some (c, i) ) + + type 'a ipath = ('a * Cycle_repr.t) * int + + let left_args = + Storage_description.One + { + rpc_arg = Cycle_repr.rpc_arg; + encoding = Cycle_repr.encoding; + compare = Cycle_repr.compare; + } + + let right_args = + Storage_description.One + { + rpc_arg = RPC_arg.int; + encoding = Data_encoding.int31; + compare = Compare.Int.compare; + } + + let args = Storage_description.(Pair (left_args, right_args)) + end + + module Owner = + Make_indexed_data_snapshotable_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["owner"] + end)) + (Snapshoted_owner_index) + (Make_index (Roll_repr.Index)) + (Signature.Public_key) + + module Snapshot_for_cycle = Cycle.Roll_snapshot + module Last_for_snapshot = Cycle.Last_roll + + let clear = Indexed_context.clear +end + +(** Votes *) + +module Vote = struct + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["votes"] + end) + + module Pred_period_kind = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["pred_period_kind"] + end) + (struct + type t = Voting_period_repr.kind + + let encoding = Voting_period_repr.kind_encoding + end) + + module Current_period = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["current_period"] + end) + (struct + type t = Voting_period_repr.t + + let encoding = Voting_period_repr.encoding + end) + + module Participation_ema = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["participation_ema"] + end) + (Int32) + + module Current_proposal = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["current_proposal"] + end) + (Protocol_hash) + + module Listings_size = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["listings_size"] + end) + (Int32) + + module Listings = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["listings"] + end)) + (Make_index (Signature.Public_key_hash)) + (Int32) + + module Proposals = + Make_data_set_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["proposals"] + end)) + (Pair + (Make_index + (Protocol_hash)) + (Make_index (Signature.Public_key_hash))) + + module Proposals_count = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["proposals_count"] + end)) + (Make_index (Signature.Public_key_hash)) + (UInt16) + + module Ballots = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["ballots"] + end)) + (Make_index (Signature.Public_key_hash)) + (struct + type t = Vote_repr.ballot + + let encoding = Vote_repr.ballot_encoding + end) +end + +(** Seed *) + +module Seed = struct + type unrevealed_nonce = Cycle.unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; + rewards : Tez_repr.t; + fees : Tez_repr.t; + } + + type nonce_status = Cycle.nonce_status = + | Unrevealed of unrevealed_nonce + | Revealed of Seed_repr.nonce + + module Nonce = struct + open Level_repr + + type context = Raw_context.t + + let mem ctxt (l : Level_repr.t) = Cycle.Nonce.mem (ctxt, l.cycle) l.level + + let get ctxt (l : Level_repr.t) = Cycle.Nonce.get (ctxt, l.cycle) l.level + + let find ctxt (l : Level_repr.t) = Cycle.Nonce.find (ctxt, l.cycle) l.level + + let update ctxt (l : Level_repr.t) v = + Cycle.Nonce.update (ctxt, l.cycle) l.level v + + let init ctxt (l : Level_repr.t) v = + Cycle.Nonce.init (ctxt, l.cycle) l.level v + + let add ctxt (l : Level_repr.t) v = + Cycle.Nonce.add (ctxt, l.cycle) l.level v + + let add_or_remove ctxt (l : Level_repr.t) v = + Cycle.Nonce.add_or_remove (ctxt, l.cycle) l.level v + + let remove_existing ctxt (l : Level_repr.t) = + Cycle.Nonce.remove_existing (ctxt, l.cycle) l.level + + let remove ctxt (l : Level_repr.t) = + Cycle.Nonce.remove (ctxt, l.cycle) l.level + end + + module For_cycle = Cycle.Seed +end + +(** Commitments *) + +module Commitments = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["commitments"] + end)) + (Make_index (Blinded_public_key_hash.Index)) + (Tez_repr) + +(** Ramp up security deposits... *) + +module Ramp_up = struct + module Rewards = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["ramp_up"; "rewards"] + end)) + (Make_index (Cycle_repr.Index)) + (struct + type t = Tez_repr.t list * Tez_repr.t list + + let encoding = + Data_encoding.( + obj2 + (req "baking_reward_per_endorsement" (list Tez_repr.encoding)) + (req "endorsement_reward" (list Tez_repr.encoding))) + end) + + module Security_deposits = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["ramp_up"; "deposits"] + end)) + (Make_index (Cycle_repr.Index)) + (struct + type t = Tez_repr.t * Tez_repr.t + + let encoding = + Data_encoding.tup2 Tez_repr.encoding Tez_repr.encoding + end) +end + +module Pending_migration_balance_updates = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["pending_migration_balance_updates"] + end) + (struct + type t = Receipt_repr.balance_updates + + let encoding = Receipt_repr.balance_updates_encoding + end) diff --git a/src/proto_009_PsFLoren/lib_protocol/storage.mli b/src/proto_009_PsFLoren/lib_protocol/storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..694161e20bdec3cff94f78b82cca871901428767 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/storage.mli @@ -0,0 +1,489 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Typed storage + + This module hides the hierarchical (key x value) database under + pre-allocated typed accessors for all persistent entities of the + tezos context. + + This interface enforces no invariant on the contents of the + database. Its goal is to centralize all accessors in order to have + a complete view over the database contents and avoid key + collisions. *) + +open Storage_sigs + +module Block_priority : sig + val get : Raw_context.t -> int tzresult Lwt.t + + val update : Raw_context.t -> int -> Raw_context.t tzresult Lwt.t + + val init : Raw_context.t -> int -> Raw_context.t tzresult Lwt.t +end + +module Roll : sig + (** Storage from this submodule must only be accessed through the + module `Roll`. *) + + module Owner : + Indexed_data_snapshotable_storage + with type key = Roll_repr.t + and type snapshot = Cycle_repr.t * int + and type value = Signature.Public_key.t + and type t := Raw_context.t + + val clear : Raw_context.t -> Raw_context.t Lwt.t + + (** The next roll to be allocated. *) + module Next : + Single_data_storage + with type value = Roll_repr.t + and type t := Raw_context.t + + (** Rolls linked lists represent both account owned and free rolls. + All rolls belongs either to the limbo list or to an owned list. *) + + (** Head of the linked list of rolls in limbo *) + module Limbo : + Single_data_storage + with type value = Roll_repr.t + and type t := Raw_context.t + + (** Rolls associated to contracts, a linked list per contract *) + module Delegate_roll_list : + Indexed_data_storage + with type key = Signature.Public_key_hash.t + and type value = Roll_repr.t + and type t := Raw_context.t + + (** Use this to iter on a linked list of rolls *) + module Successor : + Indexed_data_storage + with type key = Roll_repr.t + and type value = Roll_repr.t + and type t := Raw_context.t + + (** The tez of a contract that are not assigned to rolls *) + module Delegate_change : + Indexed_data_storage + with type key = Signature.Public_key_hash.t + and type value = Tez_repr.t + and type t := Raw_context.t + + (** Index of the randomly selected roll snapshot of a given cycle. *) + module Snapshot_for_cycle : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = int + and type t := Raw_context.t + + (** Last roll in the snapshoted roll allocation of a given cycle. *) + module Last_for_snapshot : + Indexed_data_storage + with type key = int + and type value = Roll_repr.t + and type t = Raw_context.t * Cycle_repr.t +end + +module Contract : sig + (** Storage from this submodule must only be accessed through the + module `Contract`. *) + + module Global_counter : sig + val get : Raw_context.t -> Z.t tzresult Lwt.t + + val update : Raw_context.t -> Z.t -> Raw_context.t tzresult Lwt.t + + val init : Raw_context.t -> Z.t -> Raw_context.t tzresult Lwt.t + end + + (** The domain of alive contracts *) + val fold : + Raw_context.t -> + init:'a -> + f:(Contract_repr.t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + val list : Raw_context.t -> Contract_repr.t list Lwt.t + + (** All the tez possessed by a contract, including rolls and change *) + module Balance : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Tez_repr.t + and type t := Raw_context.t + + (** Frozen balance, see 'delegate_storage.mli' for more explanation. + Always update `Delegates_with_frozen_balance` accordingly. *) + module Frozen_deposits : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Tez_repr.t + and type t = Raw_context.t * Contract_repr.t + + module Frozen_fees : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Tez_repr.t + and type t = Raw_context.t * Contract_repr.t + + module Frozen_rewards : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Tez_repr.t + and type t = Raw_context.t * Contract_repr.t + + (** The manager of a contract *) + module Manager : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Manager_repr.t + and type t := Raw_context.t + + (** The delegate of a contract, if any. *) + module Delegate : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Signature.Public_key_hash.t + and type t := Raw_context.t + + (** All contracts (implicit and originated) that are delegated, if any *) + module Delegated : + Data_set_storage + with type elt = Contract_repr.t + and type t = Raw_context.t * Contract_repr.t + + module Inactive_delegate : + Data_set_storage with type elt = Contract_repr.t and type t = Raw_context.t + + (** The cycle where the delegate should be deactivated. *) + module Delegate_desactivation : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Cycle_repr.t + and type t := Raw_context.t + + module Counter : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Z.t + and type t := Raw_context.t + + module Code : + Non_iterable_indexed_carbonated_data_storage + with type key = Contract_repr.t + and type value = Script_repr.lazy_expr + and type t := Raw_context.t + + module Storage : + Non_iterable_indexed_carbonated_data_storage + with type key = Contract_repr.t + and type value = Script_repr.lazy_expr + and type t := Raw_context.t + + (** Current storage space in bytes. + Includes code, global storage and big map elements. *) + module Used_storage_space : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Z.t + and type t := Raw_context.t + + (** Maximal space available without needing to burn new fees. *) + module Paid_storage_space : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Z.t + and type t := Raw_context.t +end + +module Big_map : sig + type id = Lazy_storage_kind.Big_map.Id.t + + module Next : sig + val incr : Raw_context.t -> (Raw_context.t * id) tzresult Lwt.t + + val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + end + + (** The domain of alive big maps *) + val fold : Raw_context.t -> init:'a -> f:(id -> 'a -> 'a Lwt.t) -> 'a Lwt.t + + val list : Raw_context.t -> id list Lwt.t + + val remove : Raw_context.t -> id -> Raw_context.t Lwt.t + + val copy : Raw_context.t -> from:id -> to_:id -> Raw_context.t tzresult Lwt.t + + type key = Raw_context.t * id + + val rpc_arg : id RPC_arg.t + + module Contents : + Non_iterable_indexed_carbonated_data_storage + with type key = Script_expr_hash.t + and type value = Script_repr.expr + and type t := key + + module Total_bytes : + Indexed_data_storage + with type key = id + and type value = Z.t + and type t := Raw_context.t + + module Key_type : + Indexed_data_storage + with type key = id + and type value = Script_repr.expr + and type t := Raw_context.t + + module Value_type : + Indexed_data_storage + with type key = id + and type value = Script_repr.expr + and type t := Raw_context.t +end + +module Sapling : sig + type id = Lazy_storage_kind.Sapling_state.Id.t + + val rpc_arg : id RPC_arg.t + + module Next : sig + val incr : Raw_context.t -> (Raw_context.t * id) tzresult Lwt.t + + val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + end + + val copy : Raw_context.t -> from:id -> to_:id -> Raw_context.t tzresult Lwt.t + + val remove : Raw_context.t -> id -> Raw_context.t Lwt.t + + module Total_bytes : + Indexed_data_storage + with type key = id + and type value = Z.t + and type t := Raw_context.t + + (* Used by both Commitments and Ciphertexts *) + module Commitments_size : + Single_data_storage + with type t := Raw_context.t * id + and type value = int64 + + module Memo_size : + Single_data_storage with type t := Raw_context.t * id and type value = int + + module Commitments : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * id + and type key = int64 + and type value = Sapling.Hash.t + + val commitments_init : Raw_context.t -> id -> Raw_context.t Lwt.t + + module Ciphertexts : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * id + and type key = int64 + and type value = Sapling.Ciphertext.t + + val ciphertexts_init : Raw_context.t -> id -> Raw_context.t Lwt.t + + module Nullifiers_size : + Single_data_storage + with type t := Raw_context.t * id + and type value = int64 + + module Nullifiers_ordered : + Non_iterable_indexed_data_storage + with type t := Raw_context.t * id + and type key = int64 + and type value = Sapling.Nullifier.t + + module Nullifiers_hashed : + Carbonated_data_set_storage + with type t := Raw_context.t * id + and type elt = Sapling.Nullifier.t + + val nullifiers_init : Raw_context.t -> id -> Raw_context.t Lwt.t + + module Roots : + Non_iterable_indexed_data_storage + with type t := Raw_context.t * id + and type key = int32 + and type value = Sapling.Hash.t + + module Roots_pos : + Single_data_storage + with type t := Raw_context.t * id + and type value = int32 + + module Roots_level : + Single_data_storage + with type t := Raw_context.t * id + and type value = Raw_level_repr.t +end + +(** Set of all registered delegates. *) +module Delegates : + Data_set_storage + with type t := Raw_context.t + and type elt = Signature.Public_key_hash.t + +(** Set of all active delegates with rolls. *) +module Active_delegates_with_rolls : + Data_set_storage + with type t := Raw_context.t + and type elt = Signature.Public_key_hash.t + +(** Set of all the delegates with frozen rewards/bonds/fees for a given cycle. *) +module Delegates_with_frozen_balance : + Data_set_storage + with type t = Raw_context.t * Cycle_repr.t + and type elt = Signature.Public_key_hash.t + +(** Votes *) + +module Vote : sig + module Pred_period_kind : + Single_data_storage + with type value = Voting_period_repr.kind + and type t := Raw_context.t + + module Current_period : + Single_data_storage + with type value = Voting_period_repr.t + and type t := Raw_context.t + + (** Participation exponential moving average, in centile of percentage *) + module Participation_ema : + Single_data_storage with type value = int32 and type t := Raw_context.t + + module Current_proposal : + Single_data_storage + with type value = Protocol_hash.t + and type t := Raw_context.t + + (** Sum of all rolls of all delegates. *) + module Listings_size : + Single_data_storage with type value = int32 and type t := Raw_context.t + + (** Contains all delegates with their assigned number of rolls. *) + module Listings : + Indexed_data_storage + with type key = Signature.Public_key_hash.t + and type value = int32 + and type t := Raw_context.t + + (** Set of protocol proposal with corresponding proposer delegate *) + module Proposals : + Data_set_storage + with type elt = Protocol_hash.t * Signature.Public_key_hash.t + and type t := Raw_context.t + + (** Keeps for each delegate the number of proposed protocols *) + module Proposals_count : + Indexed_data_storage + with type key = Signature.Public_key_hash.t + and type value = int + and type t := Raw_context.t + + (** Contains for each delegate its ballot *) + module Ballots : + Indexed_data_storage + with type key = Signature.Public_key_hash.t + and type value = Vote_repr.ballot + and type t := Raw_context.t +end + +(** Seed *) + +module Seed : sig + (** Storage from this submodule must only be accessed through the + module `Seed`. *) + + type unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; + rewards : Tez_repr.t; + fees : Tez_repr.t; + } + + type nonce_status = + | Unrevealed of unrevealed_nonce + | Revealed of Seed_repr.nonce + + module Nonce : + Non_iterable_indexed_data_storage + with type key := Level_repr.t + and type value := nonce_status + and type t := Raw_context.t + + module For_cycle : sig + val init : + Raw_context.t -> + Cycle_repr.t -> + Seed_repr.seed -> + Raw_context.t tzresult Lwt.t + + val get : Raw_context.t -> Cycle_repr.t -> Seed_repr.seed tzresult Lwt.t + + val remove_existing : + Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t + end +end + +(** Commitments *) + +module Commitments : + Indexed_data_storage + with type key = Blinded_public_key_hash.t + and type value = Tez_repr.t + and type t := Raw_context.t + +(** Ramp up security deposits... *) + +module Ramp_up : sig + module Rewards : + Indexed_data_storage + with type key = Cycle_repr.t + and type value := Tez_repr.t list * Tez_repr.t list + (* baking rewards per endorsement * endorsement rewards *) + and type t := Raw_context.t + + module Security_deposits : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Tez_repr.t * Tez_repr.t + (* baking * endorsement *) + and type t := Raw_context.t +end + +module Pending_migration_balance_updates : + Single_data_storage + with type value = Receipt_repr.balance_updates + and type t := Raw_context.t diff --git a/src/proto_009_PsFLoren/lib_protocol/storage_costs.ml b/src/proto_009_PsFLoren/lib_protocol/storage_costs.ml new file mode 100644 index 0000000000000000000000000000000000000000..dae9e12456fec9eb0f2278b2a320fb05f93863ce --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/storage_costs.ml @@ -0,0 +1,43 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* The model for read accesses is the following: + + cost(path_length, read_bytes) = 200_000 + 5000 * path_length + 2 * read_bytes +*) +let read_access ~path_length ~read_bytes = + let open Saturation_repr in + let base_cost = safe_int (200_000 + (5000 * path_length)) in + Gas_limit_repr.atomic_step_cost + (add base_cost (mul (safe_int 2) (safe_int read_bytes))) + +(* The model for write accesses is the following: + + cost(written_bytes) = 200_000 + 4 * written_bytes +*) +let write_access ~written_bytes = + let open Saturation_repr in + Gas_limit_repr.atomic_step_cost + (add (safe_int 200_000) (mul (safe_int 4) (safe_int written_bytes))) diff --git a/src/proto_009_PsFLoren/lib_protocol/storage_costs.mli b/src/proto_009_PsFLoren/lib_protocol/storage_costs.mli new file mode 100644 index 0000000000000000000000000000000000000000..0b91ce04eaaeef355cb5c30393331439c413ccf4 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/storage_costs.mli @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Cost of reading [read_bytes] at a key of length [path_length]. *) +val read_access : path_length:int -> read_bytes:int -> Gas_limit_repr.cost + +(** Cost of performing a single write access, writing [written_bytes] bytes. *) +val write_access : written_bytes:int -> Gas_limit_repr.cost diff --git a/src/proto_009_PsFLoren/lib_protocol/storage_description.ml b/src/proto_009_PsFLoren/lib_protocol/storage_description.ml new file mode 100644 index 0000000000000000000000000000000000000000..81ca5292d2d20fa19992fc45227941d0f0c9224d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/storage_description.ml @@ -0,0 +1,390 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module StringMap = Map.Make (String) + +type 'key t = 'key desc_with_path + +(** [desc_with_path] describes a position in the storage. It's composed + [rev_path] which is the reverse path up to the position, and [dir] the + position's [description]. [rev_path] is only useful in case of an error to + print a descriptive message. [List.rev rev_path] is a storage's path that + contains no conflict and allow the registration of a [dir]'s storage. *) +and 'key desc_with_path = { + rev_path : string list; + mutable dir : 'key description; +} + +and 'key description = + | Empty : 'key description + | Value : { + get : 'key -> 'a option tzresult Lwt.t; + encoding : 'a Data_encoding.t; + } + -> 'key description + | NamedDir : 'key t StringMap.t -> 'key description + | IndexedDir : { + arg : 'a RPC_arg.t; + arg_encoding : 'a Data_encoding.t; + list : 'key -> 'a list tzresult Lwt.t; + subdir : ('key * 'a) t; + } + -> 'key description + +let rec pp : type a. Format.formatter -> a t -> unit = + fun ppf {dir; _} -> + match dir with + | Empty -> + Format.fprintf ppf "Empty" + | Value _e -> + Format.fprintf ppf "Value" + | NamedDir map -> + Format.fprintf + ppf + "@[%a@]" + (Format.pp_print_list pp_item) + (StringMap.bindings map) + | IndexedDir {arg; subdir; _} -> + let name = Format.asprintf "<%s>" (RPC_arg.descr arg).name in + pp_item ppf (name, subdir) + +and pp_item : type a. Format.formatter -> string * a t -> unit = + fun ppf (name, desc) -> Format.fprintf ppf "@[%s@ %a@]" name pp desc + +let pp_rev_path ppf path = + Format.fprintf + ppf + "[%a]" + Format.( + pp_print_list + ~pp_sep:(fun ppf () -> pp_print_string ppf " / ") + pp_print_string) + (List.rev path) + +let rec register_named_subcontext : type r. r t -> string list -> r t = + fun ({rev_path; dir} as desc) names -> + match (dir, names) with + | (_, []) -> + desc + | (Value _, _) | (IndexedDir _, _) -> + Format.kasprintf + invalid_arg + "Could not register a named subcontext at %a because of an existing %a." + pp_rev_path + rev_path + pp + desc + | (Empty, name :: names) -> + let subdir = {rev_path = name :: rev_path; dir = Empty} in + desc.dir <- NamedDir (StringMap.singleton name subdir) ; + register_named_subcontext subdir names + | (NamedDir map, name :: names) -> + let subdir = + match StringMap.find_opt name map with + | Some subdir -> + subdir + | None -> + let subdir = {rev_path = name :: rev_path; dir = Empty} in + desc.dir <- NamedDir (StringMap.add name subdir map) ; + subdir + in + register_named_subcontext subdir names + +type (_, _, _) args = + | One : { + rpc_arg : 'a RPC_arg.t; + encoding : 'a Data_encoding.t; + compare : 'a -> 'a -> int; + } + -> ('key, 'a, 'key * 'a) args + | Pair : + ('key, 'a, 'inter_key) args * ('inter_key, 'b, 'sub_key) args + -> ('key, 'a * 'b, 'sub_key) args + +let rec unpack : type a b c. (a, b, c) args -> c -> a * b = function + | One _ -> + fun x -> x + | Pair (l, r) -> + let unpack_l = unpack l in + let unpack_r = unpack r in + fun x -> + let (c, d) = unpack_r x in + let (b, a) = unpack_l c in + (b, (a, d)) + +let rec pack : type a b c. (a, b, c) args -> a -> b -> c = function + | One _ -> + fun b a -> (b, a) + | Pair (l, r) -> + let pack_l = pack l in + let pack_r = pack r in + fun b (a, d) -> + let c = pack_l b a in + pack_r c d + +let rec compare : type a b c. (a, b, c) args -> b -> b -> int = function + | One {compare; _} -> + compare + | Pair (l, r) -> ( + let compare_l = compare l in + let compare_r = compare r in + fun (a1, b1) (a2, b2) -> + match compare_l a1 a2 with 0 -> compare_r b1 b2 | x -> x ) + +let destutter equal l = + match l with + | [] -> + [] + | (i, _) :: l -> + let rec loop acc i = function + | [] -> + acc + | (j, _) :: l -> + if equal i j then loop acc i l else loop (j :: acc) j l + in + loop [i] i l + +let rec register_indexed_subcontext : + type r a b. + r t -> list:(r -> a list tzresult Lwt.t) -> (r, a, b) args -> b t = + fun ({dir; rev_path = desc_path} as desc) ~list path -> + match path with + | Pair (left, right) -> + let compare_left = compare left in + let equal_left x y = Compare.Int.(compare_left x y = 0) in + let list_left r = list r >|=? fun l -> destutter equal_left l in + let list_right r = + let (a, k) = unpack left r in + list a + >|=? fun l -> + List.map snd (List.filter (fun (x, _) -> equal_left x k) l) + in + register_indexed_subcontext + (register_indexed_subcontext desc ~list:list_left left) + ~list:list_right + right + | One {rpc_arg = arg; encoding = arg_encoding; _} -> ( + match dir with + | Value _ | NamedDir _ -> + Format.kasprintf + invalid_arg + "Could not register an indexed subcontext at %a because of an \ + existing %a." + pp_rev_path + desc_path + pp + desc + | Empty -> + let subdir = + { + rev_path = + Format.sprintf "(Maybe of %s)" RPC_arg.(descr arg).name + :: desc.rev_path; + dir = Empty; + } + in + desc.dir <- IndexedDir {arg; arg_encoding; list; subdir} ; + subdir + | IndexedDir {arg = inner_arg; subdir; _} -> ( + match RPC_arg.eq arg inner_arg with + | None -> + Format.kasprintf + invalid_arg + "An indexed subcontext at %a already exists but has a different \ + argument: `%s` <> `%s`." + pp_rev_path + desc_path + (RPC_arg.descr arg).name + (RPC_arg.descr inner_arg).name + | Some RPC_arg.Eq -> + subdir ) ) + +let register_value : + type a b. + a t -> get:(a -> b option tzresult Lwt.t) -> b Data_encoding.t -> unit = + fun ({dir; rev_path} as desc) ~get encoding -> + match dir with + | Empty -> + desc.dir <- Value {get; encoding} + | _ -> + Format.kasprintf + invalid_arg + "Could not register a value at %a because of an existing %a." + pp_rev_path + rev_path + pp + desc + +let create () = {rev_path = []; dir = Empty} + +module type INDEX = sig + type t + + val path_length : int + + val to_path : t -> string list -> string list + + val of_path : string list -> t option + + val rpc_arg : t RPC_arg.t + + val encoding : t Data_encoding.t + + val compare : t -> t -> int +end + +type _ handler = + | Handler : { + encoding : 'a Data_encoding.t; + get : 'key -> int -> 'a tzresult Lwt.t; + } + -> 'key handler + +type _ opt_handler = + | Opt_handler : { + encoding : 'a Data_encoding.t; + get : 'key -> int -> 'a option tzresult Lwt.t; + } + -> 'key opt_handler + +let rec combine_object = function + | [] -> + Handler {encoding = Data_encoding.unit; get = (fun _ _ -> return_unit)} + | (name, Opt_handler handler) :: fields -> + let (Handler handlers) = combine_object fields in + Handler + { + encoding = + Data_encoding.merge_objs + Data_encoding.(obj1 (opt name (dynamic_size handler.encoding))) + handlers.encoding; + get = + (fun k i -> + handler.get k i + >>=? fun v1 -> handlers.get k i >|=? fun v2 -> (v1, v2)); + } + +type query = {depth : int} + +let depth_query = + let open RPC_query in + query (fun depth -> {depth}) + |+ field "depth" RPC_arg.int 0 (fun t -> t.depth) + |> seal + +let build_directory : type key. key t -> key RPC_directory.t = + fun dir -> + let rpc_dir = ref (RPC_directory.empty : key RPC_directory.t) in + let register : type ikey. (key, ikey) RPC_path.t -> ikey opt_handler -> unit + = + fun path (Opt_handler {encoding; get}) -> + let service = + RPC_service.get_service ~query:depth_query ~output:encoding path + in + rpc_dir := + RPC_directory.register !rpc_dir service (fun k q () -> + get k (q.depth + 1) + >|=? function None -> raise Not_found | Some x -> x) + in + let rec build_handler : + type ikey. ikey t -> (key, ikey) RPC_path.t -> ikey opt_handler = + fun {dir; _} path -> + match dir with + | Empty -> + Opt_handler + {encoding = Data_encoding.unit; get = (fun _ _ -> return_none)} + | Value {get; encoding} -> + let handler = + Opt_handler + { + encoding; + get = + (fun k i -> if Compare.Int.(i < 0) then return_none else get k); + } + in + register path handler ; handler + | NamedDir map -> + let fields = StringMap.bindings map in + let fields = + List.map + (fun (name, dir) -> + (name, build_handler dir RPC_path.(path / name))) + fields + in + let (Handler handler) = combine_object fields in + let handler = + Opt_handler + { + encoding = handler.encoding; + get = + (fun k i -> + if Compare.Int.(i < 0) then return_none + else handler.get k (i - 1) >>=? fun v -> return_some v); + } + in + register path handler ; handler + | IndexedDir {arg; arg_encoding; list; subdir} -> + let (Opt_handler handler) = + build_handler subdir RPC_path.(path /: arg) + in + let encoding = + let open Data_encoding in + union + [ case + (Tag 0) + ~title:"Leaf" + (dynamic_size arg_encoding) + (function (key, None) -> Some key | _ -> None) + (fun key -> (key, None)); + case + (Tag 1) + ~title:"Dir" + (tup2 + (dynamic_size arg_encoding) + (dynamic_size handler.encoding)) + (function (key, Some value) -> Some (key, value) | _ -> None) + (fun (key, value) -> (key, Some value)) ] + in + let get k i = + if Compare.Int.(i < 0) then return_none + else if Compare.Int.(i = 0) then return_some [] + else + list k + >>=? fun keys -> + map_s + (fun key -> + if Compare.Int.(i = 1) then return (key, None) + else handler.get (k, key) (i - 1) >|=? fun value -> (key, value)) + keys + >>=? fun values -> return_some values + in + let handler = + Opt_handler + {encoding = Data_encoding.(list (dynamic_size encoding)); get} + in + register path handler ; handler + in + ignore (build_handler dir RPC_path.open_root : key opt_handler) ; + !rpc_dir diff --git a/src/proto_009_PsFLoren/lib_protocol/storage_description.mli b/src/proto_009_PsFLoren/lib_protocol/storage_description.mli new file mode 100644 index 0000000000000000000000000000000000000000..ccd7587082e9458e2996a89bc6d617ad9e9fe95c --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/storage_description.mli @@ -0,0 +1,95 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Typed description of the key-value context. *) +type 'key t + +(** Trivial display of the key-value context layout. *) +val pp : Format.formatter -> 'key t -> unit + +(** Export an RPC hierarchy for querying the context. There is one service + by possible path in the context. Services for "directory" are able to + aggregate in one JSON object the whole subtree. *) +val build_directory : 'key t -> 'key RPC_directory.t + +(** Create a empty context description, + keys will be registered by side effects. *) +val create : unit -> 'key t + +(** Register a single key accessor at a given path. *) +val register_value : + 'key t -> + get:('key -> 'a option tzresult Lwt.t) -> + 'a Data_encoding.t -> + unit + +(** Return a description for a prefixed fragment of the given context. + All keys registered in the subcontext will be shared by the external + context *) +val register_named_subcontext : 'key t -> string list -> 'key t + +(** Description of an index as a sequence of `RPC_arg.t`. *) +type (_, _, _) args = + | One : { + rpc_arg : 'a RPC_arg.t; + encoding : 'a Data_encoding.t; + compare : 'a -> 'a -> int; + } + -> ('key, 'a, 'key * 'a) args + | Pair : + ('key, 'a, 'inter_key) args * ('inter_key, 'b, 'sub_key) args + -> ('key, 'a * 'b, 'sub_key) args + +(** Return a description for a indexed sub-context. + All keys registered in the subcontext will be shared by the external + context. One should provide a function to list all the registered + index in the context. *) +val register_indexed_subcontext : + 'key t -> + list:('key -> 'arg list tzresult Lwt.t) -> + ('key, 'arg, 'sub_key) args -> + 'sub_key t + +(** Helpers for manipulating and defining indexes. *) + +val pack : ('key, 'a, 'sub_key) args -> 'key -> 'a -> 'sub_key + +val unpack : ('key, 'a, 'sub_key) args -> 'sub_key -> 'key * 'a + +module type INDEX = sig + type t + + val path_length : int + + val to_path : t -> string list -> string list + + val of_path : string list -> t option + + val rpc_arg : t RPC_arg.t + + val encoding : t Data_encoding.t + + val compare : t -> t -> int +end diff --git a/src/proto_009_PsFLoren/lib_protocol/storage_functors.ml b/src/proto_009_PsFLoren/lib_protocol/storage_functors.ml new file mode 100644 index 0000000000000000000000000000000000000000..7a6af8c1504ec4db4eff18b36a6bbb9947356f38 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/storage_functors.ml @@ -0,0 +1,1171 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Storage_sigs + +module Registered = struct + let ghost = false +end + +module Ghost = struct + let ghost = true +end + +module Make_encoder (V : VALUE) = struct + let of_bytes ~key b = + match Data_encoding.Binary.of_bytes V.encoding b with + | None -> + error (Raw_context.Storage_error (Corrupted_data (key ()))) + | Some v -> + Ok v + + let to_bytes v = + match Data_encoding.Binary.to_bytes V.encoding v with + | Some b -> + b + | None -> + Bytes.empty +end + +let len_name = "len" + +let data_name = "data" + +let encode_len_value bytes = + let length = Bytes.length bytes in + Data_encoding.(Binary.to_bytes_exn int31) length + +let decode_len_value key len = + match Data_encoding.(Binary.of_bytes int31) len with + | None -> + error (Raw_context.Storage_error (Corrupted_data key)) + | Some len -> + ok len + +module Make_subcontext (R : REGISTER) (C : Raw_context.T) (N : NAME) : + Raw_context.T with type t = C.t = struct + type t = C.t + + let to_key k = N.name @ k + + let mem t k = C.mem t (to_key k) + + let mem_tree t k = C.mem_tree t (to_key k) + + let get t k = C.get t (to_key k) + + let get_tree t k = C.get_tree t (to_key k) + + let find t k = C.find t (to_key k) + + let find_tree t k = C.find_tree t (to_key k) + + let add t k v = C.add t (to_key k) v + + let add_tree t k v = C.add_tree t (to_key k) v + + let init t k v = C.init t (to_key k) v + + let init_tree t k v = C.init_tree t (to_key k) v + + let update t k v = C.update t (to_key k) v + + let update_tree t k v = C.update_tree t (to_key k) v + + let add_or_remove t k v = C.add_or_remove t (to_key k) v + + let add_or_remove_tree t k v = C.add_or_remove_tree t (to_key k) v + + let remove_existing t k = C.remove_existing t (to_key k) + + let remove_existing_tree t k = C.remove_existing_tree t (to_key k) + + let remove t k = C.remove t (to_key k) + + let list t ?offset ?length k = C.list t ?offset ?length (to_key k) + + let fold ?depth t k ~init ~f = C.fold ?depth t (to_key k) ~init ~f + + module Tree = C.Tree + + let project = C.project + + let absolute_key c k = C.absolute_key c (to_key k) + + type error += Block_quota_exceeded = C.Block_quota_exceeded + + type error += Operation_quota_exceeded = C.Operation_quota_exceeded + + let consume_gas = C.consume_gas + + let check_enough_gas = C.check_enough_gas + + let description = + let description = + if R.ghost then Storage_description.create () else C.description + in + Storage_description.register_named_subcontext description N.name +end + +module Make_single_data_storage + (R : REGISTER) + (C : Raw_context.T) + (N : NAME) + (V : VALUE) : Single_data_storage with type t = C.t and type value = V.t = +struct + type t = C.t + + type context = t + + type value = V.t + + let mem t = C.mem t N.name + + include Make_encoder (V) + + let get t = + C.get t N.name + >>=? fun b -> + let key () = C.absolute_key t N.name in + Lwt.return (of_bytes ~key b) + + let find t = + C.find t N.name + >|= function + | None -> + ok_none + | Some b -> + let key () = C.absolute_key t N.name in + of_bytes ~key b >|? fun v -> Some v + + let init t v = C.init t N.name (to_bytes v) >|=? fun t -> C.project t + + let update t v = C.update t N.name (to_bytes v) >|=? fun t -> C.project t + + let add t v = C.add t N.name (to_bytes v) >|= fun t -> C.project t + + let add_or_remove t v = + C.add_or_remove t N.name (Option.map to_bytes v) >|= fun t -> C.project t + + let remove t = C.remove t N.name >|= fun t -> C.project t + + let remove_existing t = C.remove_existing t N.name >|=? fun t -> C.project t + + let () = + let open Storage_description in + let description = + if R.ghost then Storage_description.create () else C.description + in + register_value + ~get:find + (register_named_subcontext description N.name) + V.encoding +end + +module type INDEX = sig + type t + + val path_length : int + + val to_path : t -> string list -> string list + + val of_path : string list -> t option + + type 'a ipath + + val args : ('a, t, 'a ipath) Storage_description.args +end + +module Pair (I1 : INDEX) (I2 : INDEX) : INDEX with type t = I1.t * I2.t = +struct + type t = I1.t * I2.t + + let path_length = I1.path_length + I2.path_length + + let to_path (x, y) l = I1.to_path x (I2.to_path y l) + + let of_path l = + match Misc.take I1.path_length l with + | None -> + None + | Some (l1, l2) -> ( + match (I1.of_path l1, I2.of_path l2) with + | (Some x, Some y) -> + Some (x, y) + | _ -> + None ) + + type 'a ipath = 'a I1.ipath I2.ipath + + let args = Storage_description.Pair (I1.args, I2.args) +end + +module Make_data_set_storage (C : Raw_context.T) (I : INDEX) : + Data_set_storage with type t = C.t and type elt = I.t = struct + type t = C.t + + type context = t + + type elt = I.t + + let inited = Bytes.of_string "inited" + + let mem s i = C.mem s (I.to_path i []) + + let add s i = C.add s (I.to_path i []) inited >|= fun t -> C.project t + + let remove s i = C.remove s (I.to_path i []) >|= fun t -> C.project t + + let clear s = C.remove s [] >|= fun t -> C.project t + + let fold s ~init ~f = + C.fold ~depth:(`Eq I.path_length) s [] ~init ~f:(fun file tree acc -> + match C.Tree.kind tree with + | `Value -> ( + match I.of_path file with None -> assert false | Some p -> f p acc ) + | `Tree -> + Lwt.return acc) + + let elements s = fold s ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) + + let () = + let open Storage_description in + let unpack = unpack I.args in + register_value (* TODO fixme 'elements...' *) + ~get:(fun c -> + let (c, k) = unpack c in + mem c k >>= function true -> return_some true | false -> return_none) + (register_indexed_subcontext + ~list:(fun c -> elements c >|= ok) + C.description + I.args) + Data_encoding.bool +end + +module Make_indexed_data_storage (C : Raw_context.T) (I : INDEX) (V : VALUE) : + Indexed_data_storage + with type t = C.t + and type key = I.t + and type value = V.t = struct + type t = C.t + + type context = t + + type key = I.t + + type value = V.t + + include Make_encoder (V) + + let mem s i = C.mem s (I.to_path i []) + + let get s i = + C.get s (I.to_path i []) + >>=? fun b -> + let key () = C.absolute_key s (I.to_path i []) in + Lwt.return (of_bytes ~key b) + + let find s i = + C.find s (I.to_path i []) + >|= function + | None -> + ok_none + | Some b -> + let key () = C.absolute_key s (I.to_path i []) in + of_bytes ~key b >|? fun v -> Some v + + let update s i v = + C.update s (I.to_path i []) (to_bytes v) >|=? fun t -> C.project t + + let init s i v = + C.init s (I.to_path i []) (to_bytes v) >|=? fun t -> C.project t + + let add s i v = + C.add s (I.to_path i []) (to_bytes v) >|= fun t -> C.project t + + let add_or_remove s i v = + C.add_or_remove s (I.to_path i []) (Option.map to_bytes v) + >|= fun t -> C.project t + + let remove s i = C.remove s (I.to_path i []) >|= fun t -> C.project t + + let remove_existing s i = + C.remove_existing s (I.to_path i []) >|=? fun t -> C.project t + + let clear s = C.remove s [] >|= fun t -> C.project t + + let fold s ~init ~f = + C.fold ~depth:(`Eq I.path_length) s [] ~init ~f:(fun file tree acc -> + C.Tree.to_value tree + >>= function + | Some v -> ( + match I.of_path file with + | None -> + assert false + | Some path -> ( + let key () = C.absolute_key s file in + match of_bytes ~key v with + | Ok v -> + f path v acc + | Error _ -> + Lwt.return acc ) ) + | None -> + Lwt.return acc) + + let fold_keys s ~init ~f = fold s ~init ~f:(fun k _ acc -> f k acc) + + let bindings s = + fold s ~init:[] ~f:(fun p v acc -> Lwt.return ((p, v) :: acc)) + + let keys s = fold_keys s ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) + + let () = + let open Storage_description in + let unpack = unpack I.args in + register_value + ~get:(fun c -> + let (c, k) = unpack c in + find c k) + (register_indexed_subcontext + ~list:(fun c -> keys c >|= ok) + C.description + I.args) + V.encoding +end + +(* Internal-use-only version of {!Make_indexed_carbonated_data_storage} to + expose fold_keys_unaccounted *) +module Make_indexed_carbonated_data_storage_INTERNAL + (C : Raw_context.T) + (I : INDEX) + (V : VALUE) = +struct + type t = C.t + + type context = t + + type key = I.t + + type value = V.t + + include Make_encoder (V) + + let data_key i = I.to_path i [data_name] + + let len_key i = I.to_path i [len_name] + + let consume_mem_gas c key = + C.consume_gas + c + (Storage_costs.read_access ~path_length:(List.length key) ~read_bytes:0) + + let existing_size c i = + C.find c (len_key i) + >|= function + | None -> + ok (0, false) + | Some len -> + decode_len_value (len_key i) len >|? fun len -> (len, true) + + let consume_read_gas get c i = + let len_key = len_key i in + get c len_key + >>=? fun len -> + Lwt.return + ( decode_len_value len_key len + >>? fun read_bytes -> + let cost = + Storage_costs.read_access + ~path_length:(List.length len_key) + ~read_bytes + in + C.consume_gas c cost ) + + (* For the future: here, we bill a generic cost for encoding the value + to bytes. It would be cleaner for users of this functor to provide + gas costs for the encoding. *) + let consume_serialize_write_gas set c i v = + let bytes = to_bytes v in + let len = Bytes.length bytes in + C.consume_gas c (Gas_limit_repr.alloc_mbytes_cost len) + >>?= fun c -> + let cost = Storage_costs.write_access ~written_bytes:len in + C.consume_gas c cost + >>?= fun c -> + set c (len_key i) (encode_len_value bytes) >|=? fun c -> (c, bytes) + + let consume_remove_gas del c i = + C.consume_gas c (Storage_costs.write_access ~written_bytes:0) + >>?= fun c -> del c (len_key i) + + let mem s i = + let key = data_key i in + consume_mem_gas s key + >>?= fun s -> C.mem s key >|= fun exists -> ok (C.project s, exists) + + let get s i = + consume_read_gas C.get s i + >>=? fun s -> + C.get s (data_key i) + >>=? fun b -> + let key () = C.absolute_key s (data_key i) in + Lwt.return (of_bytes ~key b >|? fun v -> (C.project s, v)) + + let find s i = + let key = data_key i in + consume_mem_gas s key + >>?= fun s -> + C.mem s key + >>= fun exists -> + if exists then get s i >|=? fun (s, v) -> (s, Some v) + else return (C.project s, None) + + let update s i v = + existing_size s i + >>=? fun (prev_size, _) -> + consume_serialize_write_gas C.update s i v + >>=? fun (s, bytes) -> + C.update s (data_key i) bytes + >|=? fun t -> + let size_diff = Bytes.length bytes - prev_size in + (C.project t, size_diff) + + let init s i v = + consume_serialize_write_gas C.init s i v + >>=? fun (s, bytes) -> + C.init s (data_key i) bytes + >|=? fun t -> + let size = Bytes.length bytes in + (C.project t, size) + + let add s i v = + let add s i v = C.add s i v >|= ok in + existing_size s i + >>=? fun (prev_size, existed) -> + consume_serialize_write_gas add s i v + >>=? fun (s, bytes) -> + add s (data_key i) bytes + >|=? fun t -> + let size_diff = Bytes.length bytes - prev_size in + (C.project t, size_diff, existed) + + let remove s i = + let remove s i = C.remove s i >|= ok in + existing_size s i + >>=? fun (prev_size, existed) -> + consume_remove_gas remove s i + >>=? fun s -> + remove s (data_key i) >|=? fun t -> (C.project t, prev_size, existed) + + let remove_existing s i = + existing_size s i + >>=? fun (prev_size, _) -> + consume_remove_gas C.remove_existing s i + >>=? fun s -> + C.remove_existing s (data_key i) >|=? fun t -> (C.project t, prev_size) + + let add_or_remove s i v = + match v with None -> remove s i | Some v -> add s i v + + let fold_keys_unaccounted s ~init ~f = + C.fold ~depth:(`Eq I.path_length) s [] ~init ~f:(fun file tree acc -> + match C.Tree.kind tree with + | `Value -> ( + match List.rev file with + | last :: _ when Compare.String.(last = len_name) -> + Lwt.return acc + | last :: rest when Compare.String.(last = data_name) -> ( + let file = List.rev rest in + match I.of_path file with + | None -> + assert false + | Some path -> + f path acc ) + | _ -> + assert false ) + | `Tree -> + Lwt.return acc) + + let keys_unaccounted s = + fold_keys_unaccounted s ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) + + let () = + let open Storage_description in + let unpack = unpack I.args in + register_value (* TODO export consumed gas ?? *) + ~get:(fun c -> + let (c, k) = unpack c in + find c k >|=? fun (_, v) -> v) + (register_indexed_subcontext + ~list:(fun c -> keys_unaccounted c >|= ok) + C.description + I.args) + V.encoding +end + +module Make_indexed_carbonated_data_storage : functor + (C : Raw_context.T) + (I : INDEX) + (V : VALUE) + -> + Non_iterable_indexed_carbonated_data_storage + with type t = C.t + and type key = I.t + and type value = V.t = + Make_indexed_carbonated_data_storage_INTERNAL + +module Make_carbonated_data_set_storage (C : Raw_context.T) (I : INDEX) : + Carbonated_data_set_storage with type t = C.t and type elt = I.t = struct + module V = struct + type t = unit + + let encoding = Data_encoding.unit + end + + module M = Make_indexed_carbonated_data_storage_INTERNAL (C) (I) (V) + + type t = M.t + + type context = t + + type elt = I.t + + let mem = M.mem + + let init s i = M.init s i () + + let remove s i = M.remove s i + + let fold_keys_unaccounted = M.fold_keys_unaccounted +end + +module Make_indexed_data_snapshotable_storage + (C : Raw_context.T) + (Snapshot_index : INDEX) + (I : INDEX) + (V : VALUE) : + Indexed_data_snapshotable_storage + with type t = C.t + and type snapshot = Snapshot_index.t + and type key = I.t + and type value = V.t = struct + type snapshot = Snapshot_index.t + + let data_name = ["current"] + + let snapshot_name = ["snapshot"] + + module C_data = + Make_subcontext (Registered) (C) + (struct + let name = data_name + end) + + module C_snapshot = + Make_subcontext (Registered) (C) + (struct + let name = snapshot_name + end) + + include Make_indexed_data_storage (C_data) (I) (V) + module Snapshot = + Make_indexed_data_storage (C_snapshot) (Pair (Snapshot_index) (I)) (V) + + let snapshot_path id = snapshot_name @ Snapshot_index.to_path id [] + + let snapshot_exists s id = C.mem_tree s (snapshot_path id) + + let err_missing_key key = Raw_context.storage_error (Missing_key (key, Copy)) + + let snapshot s id = + C.find_tree s data_name + >>= function + | None -> + Lwt.return (err_missing_key data_name) + | Some tree -> + C.add_tree s (snapshot_path id) tree >|= (fun t -> C.project t) >|= ok + + let delete_snapshot s id = + C.remove s (snapshot_path id) >|= fun t -> C.project t +end + +module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX) : + Indexed_raw_context + with type t = C.t + and type key = I.t + and type 'a ipath = 'a I.ipath = struct + type t = C.t + + type context = t + + type key = I.t + + type 'a ipath = 'a I.ipath + + let clear t = C.remove t [] >|= fun t -> C.project t + + let fold_keys t ~init ~f = + C.fold ~depth:(`Eq I.path_length) t [] ~init ~f:(fun path tree acc -> + match C.Tree.kind tree with + | `Tree -> ( + match I.of_path path with + | None -> + assert false + | Some path -> + f path acc ) + | `Value -> + Lwt.return acc) + + let keys t = fold_keys t ~init:[] ~f:(fun i acc -> Lwt.return (i :: acc)) + + let err_missing_key key = Raw_context.storage_error (Missing_key (key, Copy)) + + let copy t ~from ~to_ = + let from = I.to_path from [] in + let to_ = I.to_path to_ [] in + C.find_tree t from + >>= function + | None -> + Lwt.return (err_missing_key from) + | Some tree -> + C.add_tree t to_ tree >|= ok + + let list t k = + C.fold ~depth:(`Eq 1) t k ~init:[] ~f:(fun k t acc -> + match C.Tree.kind t with + | `Value -> + Lwt.return (`Key k :: acc) + | `Tree -> + Lwt.return (`Dir k :: acc)) + + let remove t k = C.remove t (I.to_path k []) + + let description = + Storage_description.register_indexed_subcontext + ~list:(fun c -> keys c >|= ok) + C.description + I.args + + let unpack = Storage_description.unpack I.args + + let pack = Storage_description.pack I.args + + module Raw_context = struct + type t = C.t I.ipath + + let to_key i k = I.to_path i k + + let mem c k = + let (t, i) = unpack c in + C.mem t (to_key i k) + + let mem_tree c k = + let (t, i) = unpack c in + C.mem_tree t (to_key i k) + + let get c k = + let (t, i) = unpack c in + C.get t (to_key i k) + + let get_tree c k = + let (t, i) = unpack c in + C.get_tree t (to_key i k) + + let find c k = + let (t, i) = unpack c in + C.find t (to_key i k) + + let find_tree c k = + let (t, i) = unpack c in + C.find_tree t (to_key i k) + + let list c ?offset ?length k = + let (t, i) = unpack c in + C.list t ?offset ?length (to_key i k) + + let init c k v = + let (t, i) = unpack c in + C.init t (to_key i k) v >|=? fun t -> pack t i + + let init_tree c k v = + let (t, i) = unpack c in + C.init_tree t (to_key i k) v >|=? fun t -> pack t i + + let update c k v = + let (t, i) = unpack c in + C.update t (to_key i k) v >|=? fun t -> pack t i + + let update_tree c k v = + let (t, i) = unpack c in + C.update_tree t (to_key i k) v >|=? fun t -> pack t i + + let add c k v = + let (t, i) = unpack c in + C.add t (to_key i k) v >|= fun t -> pack t i + + let add_tree c k v = + let (t, i) = unpack c in + C.add_tree t (to_key i k) v >|= fun t -> pack t i + + let add_or_remove c k v = + let (t, i) = unpack c in + C.add_or_remove t (to_key i k) v >|= fun t -> pack t i + + let add_or_remove_tree c k v = + let (t, i) = unpack c in + C.add_or_remove_tree t (to_key i k) v >|= fun t -> pack t i + + let remove_existing c k = + let (t, i) = unpack c in + C.remove_existing t (to_key i k) >|=? fun t -> pack t i + + let remove_existing_tree c k = + let (t, i) = unpack c in + C.remove_existing_tree t (to_key i k) >|=? fun t -> pack t i + + let remove c k = + let (t, i) = unpack c in + C.remove t (to_key i k) >|= fun t -> pack t i + + let fold ?depth c k ~init ~f = + let (t, i) = unpack c in + C.fold ?depth t (to_key i k) ~init ~f + + module Tree = struct + include C.Tree + + let empty c = + let (t, _) = unpack c in + C.Tree.empty t + end + + let project c = + let (t, _) = unpack c in + C.project t + + let absolute_key c k = + let (t, i) = unpack c in + C.absolute_key t (to_key i k) + + type error += Block_quota_exceeded = C.Block_quota_exceeded + + type error += Operation_quota_exceeded = C.Operation_quota_exceeded + + let consume_gas c g = + let (t, i) = unpack c in + C.consume_gas t g >>? fun t -> ok (pack t i) + + let check_enough_gas c g = + let (t, _i) = unpack c in + C.check_enough_gas t g + + let description = description + end + + let resolve t prefix = + let rec loop i prefix = function + | [] when Compare.Int.(i = I.path_length) -> ( + match I.of_path prefix with + | None -> + assert false + | Some path -> + Lwt.return [path] ) + | [] -> + list t prefix + >>= fun prefixes -> + Lwt_list.map_s + (function `Key prefix | `Dir prefix -> loop (i + 1) prefix []) + prefixes + >|= List.flatten + | [d] when Compare.Int.(i = I.path_length - 1) -> + if Compare.Int.(i >= I.path_length) then invalid_arg "IO.resolve" ; + list t prefix + >>= fun prefixes -> + Lwt_list.map_s + (function + | `Key prefix | `Dir prefix -> ( + match + Misc.remove_prefix ~prefix:d (List.hd (List.rev prefix)) + with + | None -> + Lwt.return_nil + | Some _ -> + loop (i + 1) prefix [] )) + prefixes + >|= List.flatten + | "" :: ds -> + list t prefix + >>= fun prefixes -> + Lwt_list.map_s + (function `Key prefix | `Dir prefix -> loop (i + 1) prefix ds) + prefixes + >|= List.flatten + | d :: ds -> ( + if Compare.Int.(i >= I.path_length) then invalid_arg "IO.resolve" ; + C.mem_tree t (prefix @ [d]) + >>= function + | true -> loop (i + 1) (prefix @ [d]) ds | false -> Lwt.return_nil ) + in + loop 0 [] prefix + + module Make_set (R : REGISTER) (N : NAME) = struct + type t = C.t + + type context = t + + type elt = I.t + + let inited = Bytes.of_string "inited" + + let mem s i = Raw_context.mem (pack s i) N.name + + let add s i = + Raw_context.add (pack s i) N.name inited + >|= fun c -> + let (s, _) = unpack c in + C.project s + + let remove s i = + Raw_context.remove (pack s i) N.name + >|= fun c -> + let (s, _) = unpack c in + C.project s + + let clear s = + fold_keys s ~init:s ~f:(fun i s -> + Raw_context.remove (pack s i) N.name + >|= fun c -> + let (s, _) = unpack c in + s) + >|= fun t -> C.project t + + let fold s ~init ~f = + fold_keys s ~init ~f:(fun i acc -> + mem s i >>= function true -> f i acc | false -> Lwt.return acc) + + let elements s = fold s ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) + + let () = + let open Storage_description in + let unpack = unpack I.args in + let description = + if R.ghost then Storage_description.create () + else Raw_context.description + in + register_value + ~get:(fun c -> + let (c, k) = unpack c in + mem c k + >>= function true -> return_some true | false -> return_none) + (register_named_subcontext description N.name) + Data_encoding.bool + end + + module Make_map (N : NAME) (V : VALUE) = struct + type t = C.t + + type context = t + + type key = I.t + + type value = V.t + + include Make_encoder (V) + + let mem s i = Raw_context.mem (pack s i) N.name + + let get s i = + Raw_context.get (pack s i) N.name + >>=? fun b -> + let key () = Raw_context.absolute_key (pack s i) N.name in + Lwt.return (of_bytes ~key b) + + let find s i = + Raw_context.find (pack s i) N.name + >|= function + | None -> + ok_none + | Some b -> + let key () = Raw_context.absolute_key (pack s i) N.name in + of_bytes ~key b >|? fun v -> Some v + + let update s i v = + Raw_context.update (pack s i) N.name (to_bytes v) + >|=? fun c -> + let (s, _) = unpack c in + C.project s + + let init s i v = + Raw_context.init (pack s i) N.name (to_bytes v) + >|=? fun c -> + let (s, _) = unpack c in + C.project s + + let add s i v = + Raw_context.add (pack s i) N.name (to_bytes v) + >|= fun c -> + let (s, _) = unpack c in + C.project s + + let add_or_remove s i v = + Raw_context.add_or_remove (pack s i) N.name (Option.map to_bytes v) + >|= fun c -> + let (s, _) = unpack c in + C.project s + + let remove s i = + Raw_context.remove (pack s i) N.name + >|= fun c -> + let (s, _) = unpack c in + C.project s + + let remove_existing s i = + Raw_context.remove_existing (pack s i) N.name + >|=? fun c -> + let (s, _) = unpack c in + C.project s + + let clear s = + fold_keys s ~init:s ~f:(fun i s -> + Raw_context.remove (pack s i) N.name + >|= fun c -> + let (s, _) = unpack c in + s) + >|= fun t -> C.project t + + let fold s ~init ~f = + fold_keys s ~init ~f:(fun i acc -> + get s i >>= function Error _ -> Lwt.return acc | Ok v -> f i v acc) + + let bindings s = + fold s ~init:[] ~f:(fun p v acc -> Lwt.return ((p, v) :: acc)) + + let fold_keys s ~init ~f = + fold_keys s ~init ~f:(fun i acc -> + mem s i >>= function false -> Lwt.return acc | true -> f i acc) + + let keys s = fold_keys s ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) + + let () = + let open Storage_description in + let unpack = unpack I.args in + register_value + ~get:(fun c -> + let (c, k) = unpack c in + find c k) + (register_named_subcontext Raw_context.description N.name) + V.encoding + end + + module Make_carbonated_map (N : NAME) (V : VALUE) = struct + type t = C.t + + type context = t + + type key = I.t + + type value = V.t + + include Make_encoder (V) + + let len_name = len_name :: N.name + + let data_name = data_name :: N.name + + let path_length = List.length N.name + 1 + + let consume_mem_gas c = + Raw_context.consume_gas + c + (Storage_costs.read_access ~path_length ~read_bytes:0) + + let existing_size c = + Raw_context.find c len_name + >|= function + | None -> + ok (0, false) + | Some len -> + decode_len_value len_name len >|? fun len -> (len, true) + + let consume_read_gas get c = + get c len_name + >>=? fun len -> + Lwt.return + ( decode_len_value len_name len + >>? fun read_bytes -> + Raw_context.consume_gas + c + (Storage_costs.read_access ~path_length ~read_bytes) ) + + let consume_write_gas set c v = + let bytes = to_bytes v in + let len = Bytes.length bytes in + Raw_context.consume_gas c (Storage_costs.write_access ~written_bytes:len) + >>?= fun c -> + set c len_name (encode_len_value bytes) >|=? fun c -> (c, bytes) + + let consume_remove_gas del c = + Raw_context.consume_gas c (Storage_costs.write_access ~written_bytes:0) + >>?= fun c -> del c len_name + + let mem s i = + consume_mem_gas (pack s i) + >>?= fun c -> + Raw_context.mem c data_name >|= fun res -> ok (Raw_context.project c, res) + + let get s i = + consume_read_gas Raw_context.get (pack s i) + >>=? fun c -> + Raw_context.get c data_name + >>=? fun b -> + let key () = Raw_context.absolute_key c data_name in + Lwt.return (of_bytes ~key b >|? fun v -> (Raw_context.project c, v)) + + let find s i = + consume_mem_gas (pack s i) + >>?= fun c -> + let (s, _) = unpack c in + Raw_context.mem (pack s i) data_name + >>= fun exists -> + if exists then get s i >|=? fun (s, v) -> (s, Some v) + else return (C.project s, None) + + let update s i v = + existing_size (pack s i) + >>=? fun (prev_size, _) -> + consume_write_gas Raw_context.update (pack s i) v + >>=? fun (c, bytes) -> + Raw_context.update c data_name bytes + >|=? fun c -> + let size_diff = Bytes.length bytes - prev_size in + (Raw_context.project c, size_diff) + + let init s i v = + consume_write_gas Raw_context.init (pack s i) v + >>=? fun (c, bytes) -> + Raw_context.init c data_name bytes + >|=? fun c -> + let size = Bytes.length bytes in + (Raw_context.project c, size) + + let add s i v = + let add c k v = Raw_context.add c k v >|= ok in + existing_size (pack s i) + >>=? fun (prev_size, existed) -> + consume_write_gas add (pack s i) v + >>=? fun (c, bytes) -> + add c data_name bytes + >|=? fun c -> + let size_diff = Bytes.length bytes - prev_size in + (Raw_context.project c, size_diff, existed) + + let remove s i = + let remove c k = Raw_context.remove c k >|= ok in + existing_size (pack s i) + >>=? fun (prev_size, existed) -> + consume_remove_gas remove (pack s i) + >>=? fun c -> + remove c data_name + >|=? fun c -> (Raw_context.project c, prev_size, existed) + + let remove_existing s i = + existing_size (pack s i) + >>=? fun (prev_size, _) -> + consume_remove_gas Raw_context.remove_existing (pack s i) + >>=? fun c -> + Raw_context.remove_existing c data_name + >|=? fun c -> (Raw_context.project c, prev_size) + + let add_or_remove s i v = + match v with None -> remove s i | Some v -> add s i v + + let () = + let open Storage_description in + let unpack = unpack I.args in + register_value + ~get:(fun c -> + let (c, k) = unpack c in + find c k >|=? fun (_, v) -> v) + (register_named_subcontext Raw_context.description N.name) + V.encoding + end +end + +module type WRAPPER = sig + type t + + type key + + val wrap : t -> key + + val unwrap : key -> t option +end + +module Wrap_indexed_data_storage + (C : Indexed_data_storage) + (K : WRAPPER with type key := C.key) = +struct + type t = C.t + + type context = C.t + + type key = K.t + + type value = C.value + + let mem ctxt k = C.mem ctxt (K.wrap k) + + let get ctxt k = C.get ctxt (K.wrap k) + + let find ctxt k = C.find ctxt (K.wrap k) + + let update ctxt k v = C.update ctxt (K.wrap k) v + + let init ctxt k v = C.init ctxt (K.wrap k) v + + let add ctxt k v = C.add ctxt (K.wrap k) v + + let add_or_remove ctxt k v = C.add_or_remove ctxt (K.wrap k) v + + let remove_existing ctxt k = C.remove_existing ctxt (K.wrap k) + + let remove ctxt k = C.remove ctxt (K.wrap k) + + let clear ctxt = C.clear ctxt + + let fold ctxt ~init ~f = + C.fold ctxt ~init ~f:(fun k v acc -> + match K.unwrap k with None -> Lwt.return acc | Some k -> f k v acc) + + let bindings s = + fold s ~init:[] ~f:(fun p v acc -> Lwt.return ((p, v) :: acc)) + + let fold_keys s ~init ~f = + C.fold_keys s ~init ~f:(fun k acc -> + match K.unwrap k with None -> Lwt.return acc | Some k -> f k acc) + + let keys s = fold_keys s ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) +end diff --git a/src/proto_009_PsFLoren/lib_protocol/storage_functors.mli b/src/proto_009_PsFLoren/lib_protocol/storage_functors.mli new file mode 100644 index 0000000000000000000000000000000000000000..31c8b1aa5e0f40d7f42603d8ae043713ca5c4bc4 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/storage_functors.mli @@ -0,0 +1,114 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Typed storage builders. *) + +open Storage_sigs + +module Registered : REGISTER + +module Ghost : REGISTER + +module Make_subcontext (R : REGISTER) (C : Raw_context.T) (N : NAME) : + Raw_context.T with type t = C.t + +module Make_single_data_storage + (R : REGISTER) + (C : Raw_context.T) + (N : NAME) + (V : VALUE) : Single_data_storage with type t = C.t and type value = V.t + +module type INDEX = sig + type t + + val path_length : int + + val to_path : t -> string list -> string list + + val of_path : string list -> t option + + type 'a ipath + + val args : ('a, t, 'a ipath) Storage_description.args +end + +module Pair (I1 : INDEX) (I2 : INDEX) : INDEX with type t = I1.t * I2.t + +module Make_data_set_storage (C : Raw_context.T) (I : INDEX) : + Data_set_storage with type t = C.t and type elt = I.t + +module Make_carbonated_data_set_storage (C : Raw_context.T) (I : INDEX) : + Carbonated_data_set_storage with type t = C.t and type elt = I.t + +module Make_indexed_data_storage (C : Raw_context.T) (I : INDEX) (V : VALUE) : + Indexed_data_storage + with type t = C.t + and type key = I.t + and type value = V.t + +module Make_indexed_carbonated_data_storage + (C : Raw_context.T) + (I : INDEX) + (V : VALUE) : + Non_iterable_indexed_carbonated_data_storage + with type t = C.t + and type key = I.t + and type value = V.t + +module Make_indexed_data_snapshotable_storage + (C : Raw_context.T) + (Snapshot : INDEX) + (I : INDEX) + (V : VALUE) : + Indexed_data_snapshotable_storage + with type t = C.t + and type snapshot = Snapshot.t + and type key = I.t + and type value = V.t + +module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX) : + Indexed_raw_context + with type t = C.t + and type key = I.t + and type 'a ipath = 'a I.ipath + +module type WRAPPER = sig + type t + + type key + + val wrap : t -> key + + val unwrap : key -> t option +end + +module Wrap_indexed_data_storage + (C : Indexed_data_storage) + (K : WRAPPER with type key := C.key) : + Indexed_data_storage + with type t = C.t + and type key = K.t + and type value = C.value diff --git a/src/proto_009_PsFLoren/lib_protocol/storage_sigs.ml b/src/proto_009_PsFLoren/lib_protocol/storage_sigs.ml new file mode 100644 index 0000000000000000000000000000000000000000..6c890225220824f7f82c812aa2965ba804f2c429 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/storage_sigs.ml @@ -0,0 +1,367 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {1 Entity Accessor Signatures} *) + +(** The generic signature of a single data accessor (a single value + bound to a specific key in the hierarchical (key x value) + database). *) +module type Single_data_storage = sig + type t + + type context = t + + (** The type of the value *) + type value + + (** Tells if the data is already defined *) + val mem : context -> bool Lwt.t + + (** Retrieve the value from the storage bucket ; returns a + {!Storage_error} if the key is not set or if the deserialisation + fails *) + val get : context -> value tzresult Lwt.t + + (** Retrieves the value from the storage bucket ; returns [None] if + the data is not initialized, or {!Storage_helpers.Storage_error} + if the deserialisation fails *) + val find : context -> value option tzresult Lwt.t + + (** Allocates the storage bucket and initializes it ; returns a + {!Storage_error Existing_key} if the bucket exists *) + val init : context -> value -> Raw_context.t tzresult Lwt.t + + (** Updates the content of the bucket ; returns a {!Storage_Error + Missing_key} if the value does not exists *) + val update : context -> value -> Raw_context.t tzresult Lwt.t + + (** Allocates the data and initializes it with a value ; just + updates it if the bucket exists *) + val add : context -> value -> Raw_context.t Lwt.t + + (** When the value is [Some v], allocates the data and initializes + it with [v] ; just updates it if the bucket exists. When the + value is [None], delete the storage bucket when the value ; does + nothing if the bucket does not exists. *) + val add_or_remove : context -> value option -> Raw_context.t Lwt.t + + (** Delete the storage bucket ; returns a {!Storage_error + Missing_key} if the bucket does not exists *) + val remove_existing : context -> Raw_context.t tzresult Lwt.t + + (** Removes the storage bucket and its contents ; does nothing if + the bucket does not exists *) + val remove : context -> Raw_context.t Lwt.t +end + +(** Restricted version of {!Indexed_data_storage} w/o iterators. *) +module type Non_iterable_indexed_data_storage = sig + type t + + type context = t + + (** An abstract type for keys *) + type key + + (** The type of values *) + type value + + (** Tells if a given key is already bound to a storage bucket *) + val mem : context -> key -> bool Lwt.t + + (** Retrieve a value from the storage bucket at a given key ; + returns {!Storage_error Missing_key} if the key is not set ; + returns {!Storage_error Corrupted_data} if the deserialisation + fails. *) + val get : context -> key -> value tzresult Lwt.t + + (** Retrieve a value from the storage bucket at a given key ; + returns [None] if the value is not set ; returns {!Storage_error + Corrupted_data} if the deserialisation fails. *) + val find : context -> key -> value option tzresult Lwt.t + + (** Updates the content of a bucket ; returns A {!Storage_Error + Missing_key} if the value does not exists. *) + val update : context -> key -> value -> Raw_context.t tzresult Lwt.t + + (** Allocates a storage bucket at the given key and initializes it ; + returns a {!Storage_error Existing_key} if the bucket exists. *) + val init : context -> key -> value -> Raw_context.t tzresult Lwt.t + + (** Allocates a storage bucket at the given key and initializes it + with a value ; just updates it if the bucket exists. *) + val add : context -> key -> value -> Raw_context.t Lwt.t + + (** When the value is [Some v], allocates the data and initializes + it with [v] ; just updates it if the bucket exists. When the + value is [None], delete the storage bucket when the value ; does + nothing if the bucket does not exists. *) + val add_or_remove : context -> key -> value option -> Raw_context.t Lwt.t + + (** Delete a storage bucket and its contents ; returns a + {!Storage_error Missing_key} if the bucket does not exists. *) + val remove_existing : context -> key -> Raw_context.t tzresult Lwt.t + + (** Removes a storage bucket and its contents ; does nothing if the + bucket does not exists. *) + val remove : context -> key -> Raw_context.t Lwt.t +end + +(** Variant of {!Non_iterable_indexed_data_storage} with gas accounting. *) +module type Non_iterable_indexed_carbonated_data_storage = sig + type t + + type context = t + + (** An abstract type for keys *) + type key + + (** The type of values *) + type value + + (** Tells if a given key is already bound to a storage bucket. + Consumes [Gas_repr.read_bytes_cost Z.zero]. *) + val mem : context -> key -> (Raw_context.t * bool) tzresult Lwt.t + + (** Retrieve a value from the storage bucket at a given key ; + returns {!Storage_error Missing_key} if the key is not set ; + returns {!Storage_error Corrupted_data} if the deserialisation + fails. + Consumes [Gas_repr.read_bytes_cost ]. *) + val get : context -> key -> (Raw_context.t * value) tzresult Lwt.t + + (** Retrieve a value from the storage bucket at a given key ; + returns [None] if the value is not set ; returns {!Storage_error + Corrupted_data} if the deserialisation fails. + Consumes [Gas_repr.read_bytes_cost ] if present + or [Gas_repr.read_bytes_cost Z.zero]. *) + val find : context -> key -> (Raw_context.t * value option) tzresult Lwt.t + + (** Updates the content of a bucket ; returns A {!Storage_Error + Missing_key} if the value does not exists. + Consumes serialization cost. + Consumes [Gas_repr.write_bytes_cost ]. + Returns the difference from the old to the new size. *) + val update : context -> key -> value -> (Raw_context.t * int) tzresult Lwt.t + + (** Allocates a storage bucket at the given key and initializes it ; + returns a {!Storage_error Existing_key} if the bucket exists. + Consumes serialization cost. + Consumes [Gas_repr.write_bytes_cost ]. + Returns the size. *) + val init : context -> key -> value -> (Raw_context.t * int) tzresult Lwt.t + + (** Allocates a storage bucket at the given key and initializes it + with a value ; just updates it if the bucket exists. + Consumes serialization cost. + Consumes [Gas_repr.write_bytes_cost ]. + Returns the difference from the old (maybe 0) to the new size, and a boolean + indicating if a value was already associated to this key. *) + val add : + context -> key -> value -> (Raw_context.t * int * bool) tzresult Lwt.t + + (** When the value is [Some v], allocates the data and initializes + it with [v] ; just updates it if the bucket exists. When the + value is [None], delete the storage bucket when the value ; does + nothing if the bucket does not exists. + Consumes serialization cost. + Consumes the same gas cost as either {!remove} or {!init_set}. + Returns the difference from the old (maybe 0) to the new size, and a boolean + indicating if a value was already associated to this key. *) + val add_or_remove : + context -> + key -> + value option -> + (Raw_context.t * int * bool) tzresult Lwt.t + + (** Delete a storage bucket and its contents ; returns a + {!Storage_error Missing_key} if the bucket does not exists. + Consumes [Gas_repr.write_bytes_cost Z.zero]. + Returns the freed size. *) + val remove_existing : context -> key -> (Raw_context.t * int) tzresult Lwt.t + + (** Removes a storage bucket and its contents ; does nothing if the + bucket does not exists. + Consumes [Gas_repr.write_bytes_cost Z.zero]. + Returns the freed size, and a boolean + indicating if a value was already associated to this key. *) + val remove : context -> key -> (Raw_context.t * int * bool) tzresult Lwt.t +end + +(** The generic signature of indexed data accessors (a set of values + of the same type indexed by keys of the same form in the + hierarchical (key x value) database). *) +module type Indexed_data_storage = sig + include Non_iterable_indexed_data_storage + + (** Empties all the keys and associated data. *) + val clear : context -> Raw_context.t Lwt.t + + (** Lists all the keys. *) + val keys : context -> key list Lwt.t + + (** Lists all the keys and associated data. *) + val bindings : context -> (key * value) list Lwt.t + + (** Iterates over all the keys and associated data. *) + val fold : + context -> init:'a -> f:(key -> value -> 'a -> 'a Lwt.t) -> 'a Lwt.t + + (** Iterate over all the keys. *) + val fold_keys : context -> init:'a -> f:(key -> 'a -> 'a Lwt.t) -> 'a Lwt.t +end + +module type Indexed_data_snapshotable_storage = sig + type snapshot + + type key + + include Indexed_data_storage with type key := key + + module Snapshot : + Indexed_data_storage + with type key = snapshot * key + and type value = value + and type t = t + + val snapshot_exists : context -> snapshot -> bool Lwt.t + + val snapshot : context -> snapshot -> Raw_context.t tzresult Lwt.t + + val delete_snapshot : context -> snapshot -> Raw_context.t Lwt.t +end + +(** The generic signature of a data set accessor (a set of values + bound to a specific key prefix in the hierarchical (key x value) + database). *) +module type Data_set_storage = sig + type t + + type context = t + + (** The type of elements. *) + type elt + + (** Tells if a elt is a member of the set *) + val mem : context -> elt -> bool Lwt.t + + (** Adds a elt is a member of the set *) + val add : context -> elt -> Raw_context.t Lwt.t + + (** Removes a elt of the set ; does nothing if not a member *) + val remove : context -> elt -> Raw_context.t Lwt.t + + (** Returns the elements of the set, deserialized in a list in no + particular order. *) + val elements : context -> elt list Lwt.t + + (** Iterates over the elements of the set. *) + val fold : context -> init:'a -> f:(elt -> 'a -> 'a Lwt.t) -> 'a Lwt.t + + (** Removes all elements in the set *) + val clear : context -> Raw_context.t Lwt.t +end + +(** Variant of {!Data_set_storage} with gas accounting. *) +module type Carbonated_data_set_storage = sig + type t + + type context = t + + (** The type of elements. *) + type elt + + (** Tells whether an elt is a member of the set. + Consumes [Gas_repr.read_bytes_cost Z.zero] *) + val mem : context -> elt -> (Raw_context.t * bool) tzresult Lwt.t + + (** Adds an elt as a member of the set. + Consumes [Gas_repr.write_bytes_cost ]. + Returns the the new size. *) + val init : context -> elt -> (Raw_context.t * int) tzresult Lwt.t + + (** Removes an elt from the set ; does nothing if not a member. + Consumes [Gas_repr.write_bytes_cost Z.zero]. + Returns the freed size, and a boolean + indicating if a value was already associated to this key. *) + val remove : context -> elt -> (Raw_context.t * int * bool) tzresult Lwt.t + + val fold_keys_unaccounted : + context -> init:'acc -> f:(elt -> 'acc -> 'acc Lwt.t) -> 'acc Lwt.t +end + +module type NAME = sig + val name : Raw_context.key +end + +module type VALUE = sig + type t + + val encoding : t Data_encoding.t +end + +module type REGISTER = sig + val ghost : bool +end + +module type Indexed_raw_context = sig + type t + + type context = t + + type key + + type 'a ipath + + val clear : context -> Raw_context.t Lwt.t + + val fold_keys : context -> init:'a -> f:(key -> 'a -> 'a Lwt.t) -> 'a Lwt.t + + val keys : context -> key list Lwt.t + + val resolve : context -> string list -> key list Lwt.t + + val remove : context -> key -> context Lwt.t + + val copy : context -> from:key -> to_:key -> context tzresult Lwt.t + + module Make_set (R : REGISTER) (N : NAME) : + Data_set_storage with type t = t and type elt = key + + module Make_map (N : NAME) (V : VALUE) : + Indexed_data_storage + with type t = t + and type key = key + and type value = V.t + + module Make_carbonated_map (N : NAME) (V : VALUE) : + Non_iterable_indexed_carbonated_data_storage + with type t = t + and type key = key + and type value = V.t + + module Raw_context : Raw_context.T with type t = t ipath +end diff --git a/src/proto_009_PsFLoren/lib_protocol/test/.ocamlformat b/src/proto_009_PsFLoren/lib_protocol/test/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_protocol/test/contracts/big_interpreter_stack.tz b/src/proto_009_PsFLoren/lib_protocol/test/contracts/big_interpreter_stack.tz new file mode 100644 index 0000000000000000000000000000000000000000..24832df0827f2300f65a71c3472cd266cbfaac3b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/contracts/big_interpreter_stack.tz @@ -0,0 +1,5 @@ +{ parameter unit ; + storage unit ; + code { CAR ; + { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { {} ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; + NIL operation; PAIR } } diff --git a/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract.tz b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract.tz new file mode 100644 index 0000000000000000000000000000000000000000..155b71db7bb0ed584f371e4168b40eda967b0520 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract.tz @@ -0,0 +1,69 @@ +# This contract manages a shielded pool with a 1 to 1 conversion with respect to +# the tez, updated by a sapling transaction. The second parameter is an optional +# implicit account used to claim funds when unshielding. +storage (sapling_state 8); +parameter (list (pair (sapling_transaction 8) (option key_hash) ) ); +code { # Stack manipulation + UNPAIR; + NIL operation; + SWAP; + DIP { SWAP}; + AMOUNT ; + SWAP ; + DIP {SWAP} ; + ITER { UNPAIR; + DIP { SWAP }; + # We verify the transaction and update the storage if the transaction is + # valid. The shielded transactions are handled here. + # The new state is pushed on top of the stack in addition to the balance + # of the transaction. If the rest of the script goes well, this state + # will be the new state of the smart contract. + SAPLING_VERIFY_UPDATE; + # In the case of an invalid transaction, we stop. + ASSERT_SOME; + UNPAIR; + # Convert the balance in mutez, keeping the signed + # balance on top of the stack and the balance in mutez as the second + # element + DUP; + DIP { ABS; # in case of negative balance i.e. shielding + PUSH mutez 1; + MUL; }; + # We have three cases now: unshielding, shielding and transfers. + # If the balance is strictly positive (i.e. unshielding), we send funds + # to the given address. + # If no address is given (see ASSERT_SOME), we stop + IFGT { + DIIP { ASSERT_SOME; + IMPLICIT_ACCOUNT }; + SWAP; + DIP { UNIT; + TRANSFER_TOKENS; + SWAP; + # Stack manipulation to order. The operations will consist of the + # TRANSFER_TOKEN operation. + DIP {CONS} ;}; + } + # If the balance is negative or 0 (i.e. shielding or transfer), + # we verify the amount transferred in the transaction is exactly the + # balance of the verify_update output. It does enforce the conversion + # 1-1 between mutez and shielded token. + # No operation is executed. + { + DIIP {SWAP}; + DIP {SWAP}; + SWAP; + SUB; + # As we transfer or shield token, an implicit account is not + # required. It is a good practice to verify. + # If an implicit account has been given, it might be an invalid + # operation or a call error. + DIIP { ASSERT_NONE;}; + SWAP; + }; + }; + DIP { + PUSH mutez 0; + ASSERT_CMPEQ;}; + SWAP; + PAIR} \ No newline at end of file diff --git a/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_double.tz b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_double.tz new file mode 100644 index 0000000000000000000000000000000000000000..89148c8c355f8acb821e384766b19411e3baa74a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_double.tz @@ -0,0 +1,33 @@ +storage (pair (sapling_state :left 8) (sapling_state :right 8) ); +parameter (pair bool (pair (sapling_transaction :left 8) (sapling_transaction :right 8)) ); +code { UNPAIR ; + UNPAIR ; + DIP {UNPAIR} ; + DIIIP {UNPAIR} ; + DIIP {SWAP} ; + IF { SAPLING_VERIFY_UPDATE ; + ASSERT_SOME ; + UNPAIR ; + DROP ; + DIP {DIP {DUP}; + SAPLING_VERIFY_UPDATE; + ASSERT_SOME ; + UNPAIR ; + DROP ; + DROP;}; + } + { DIP { DUP}; + SAPLING_VERIFY_UPDATE; + ASSERT_SOME; + UNPAIR; + DROP; + DROP ; + DIP { SAPLING_VERIFY_UPDATE ; + ASSERT_SOME ; + UNPAIR; + DROP ; + }}; + PAIR; + NIL operation; + PAIR; + } diff --git a/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_drop.tz b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_drop.tz new file mode 100644 index 0000000000000000000000000000000000000000..b7e1b3912ff9b07c320036ff599fa3b01a498f50 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_drop.tz @@ -0,0 +1,14 @@ +storage (unit); +parameter (list (sapling_transaction 8)); +code { UNPAIR ; + SAPLING_EMPTY_STATE 8; + SWAP ; + ITER { SAPLING_VERIFY_UPDATE ; + ASSERT_SOME ; + UNPAIR ; + DROP ; + } ; + DROP ; + NIL operation; + PAIR; + } diff --git a/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_send.tz b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_send.tz new file mode 100644 index 0000000000000000000000000000000000000000..6eedc9dbc619b1ba4b0e7e6a603d73ea510cfe41 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_send.tz @@ -0,0 +1,20 @@ +storage (unit); +parameter (pair (contract (or (sapling_transaction 8) (sapling_state 8))) (sapling_transaction 8)); +code { UNPAIR ; + UNPAIR; + SWAP ; + SAPLING_EMPTY_STATE 8; + SWAP ; + SAPLING_VERIFY_UPDATE ; + ASSERT_SOME ; + UNPAIR ; + DROP ; + PUSH mutez 0; + SWAP ; + RIGHT (sapling_transaction 8); + TRANSFER_TOKENS; + NIL operation; + SWAP; + CONS; + PAIR; + } diff --git a/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_state_as_arg.tz b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_state_as_arg.tz new file mode 100644 index 0000000000000000000000000000000000000000..e8a96df046ee88f93be180d95076451ee166c894 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_contract_state_as_arg.tz @@ -0,0 +1,18 @@ +storage (option (sapling_transaction 8)); +parameter (or (sapling_transaction 8) (sapling_state 8)); +code { UNPAIR ; + IF_LEFT + { + DIP {DROP;}; + SOME; + } + { DIP {ASSERT_SOME;}; + SWAP ; + SAPLING_VERIFY_UPDATE; + ASSERT_SOME; + DROP ; + NONE (sapling_transaction 8) ; + }; + NIL operation; + PAIR; + } diff --git a/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_push_sapling_state.tz b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_push_sapling_state.tz new file mode 100644 index 0000000000000000000000000000000000000000..8d1db432bf2ee6ea891c0ccd120fcdbb4618c4b4 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_push_sapling_state.tz @@ -0,0 +1,11 @@ +# Attempt to use `PUSH sapling_state 0` where 0 is the ID of a sapling state. +# sapling_state is not allowed in the instruction PUSH. +parameter unit; +storage unit; +code { DROP; + PUSH (sapling_state 8) 0; + DROP; + PUSH unit Unit; + NIL operation; + PAIR; + } diff --git a/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_use_existing_state.tz b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_use_existing_state.tz new file mode 100644 index 0000000000000000000000000000000000000000..b637870653f8464e91407684ab47b65190ed2111 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/contracts/sapling_use_existing_state.tz @@ -0,0 +1,12 @@ +parameter (pair (sapling_transaction 8) (sapling_state 8)); +storage (sapling_state 8); +code { UNPAIR; + UNPAIR; + DIIP { DROP }; + SAPLING_VERIFY_UPDATE; + ASSERT_SOME; + UNPAIR; + DROP; + NIL operation; + PAIR; + } diff --git a/src/proto_009_PsFLoren/lib_protocol/test/dune b/src/proto_009_PsFLoren/lib_protocol/test/dune new file mode 100644 index 0000000000000000000000000000000000000000..36e1f5d899a71f2f28e9698e67a82e852f2b4a48 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/dune @@ -0,0 +1,61 @@ +(executables + (names main saturation_fuzzing) + (libraries tezos-base + tezos-micheline + tezos-protocol-environment + alcotest-lwt + crowbar + tezos-009-PsFLoren-test-helpers + tezos-stdlib-unix + tezos-client-base + tezos-protocol-009-PsFLoren-parameters + tezos-test-services + tezos-sapling + astring) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_micheline + -open Tezos_client_009_PsFLoren + -open Tezos_protocol_009_PsFLoren + -open Tezos_protocol_environment_009_PsFLoren + -open Tezos_009_PsFLoren_test_helpers + -open Tezos_test_services))) + +(rule + (alias buildtest) + (package tezos-protocol-009-PsFLoren-tests) + (deps main.exe) + (action (progn))) + +(rule + (copy %{lib:tezos-protocol-009-PsFLoren-parameters:test-parameters.json} + protocol_parameters.json)) + +; runs only the `Quick tests +(rule + (alias runtest_proto_009_PsFLoren) + (deps (glob_files contracts/*)) + (package tezos-protocol-009-PsFLoren-tests) + (action (run %{exe:main.exe} -v -q))) + +; runs both `Quick and `Slow tests +(rule + (alias runtest_slow) + (deps (glob_files contracts/*)) + (package tezos-protocol-009-PsFLoren-tests) + (action (run %{exe:main.exe} -v))) + +(rule + (alias runtest_saturation_fuzzing) + (package tezos-protocol-009-PsFLoren-tests) + (action (run %{exe:saturation_fuzzing.exe}))) + +(rule + (alias runtest) + (package tezos-protocol-009-PsFLoren-tests) + (deps (alias runtest_proto_009_PsFLoren) (alias runtest_saturation_fuzzing)) + (action (progn))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/.ocamlformat b/src/proto_009_PsFLoren/lib_protocol/test/helpers/.ocamlformat new file mode 100644 index 0000000000000000000000000000000000000000..8278a132e3d6f6c868be4c6e0a012089319d0bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/.ocamlformat @@ -0,0 +1,12 @@ +version=0.10 +wrap-fun-args=false +let-binding-spacing=compact +field-space=loose +break-separators=after-and-docked +sequence-style=separator +doc-comments=before +margin=80 +module-item-spacing=sparse +parens-tuple=always +parens-tuple-patterns=always +break-string-literals=newlines-and-wrap diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/README.md b/src/proto_009_PsFLoren/lib_protocol/test/helpers/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b071cfb4ec038daa53226eb6a5742579144e4598 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/README.md @@ -0,0 +1,3 @@ +## Helpers to build unit/integration tests for the protocol + +The OPAM package `tezos-alpha-test-helpers` contains helpers to build unit/integration tests, like forging a block, a context, nonces, operations, etc. diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/account.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/account.ml new file mode 100644 index 0000000000000000000000000000000000000000..05d78b0bbee8488d54da4dbfb3ab85545e4b96c2 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/account.ml @@ -0,0 +1,101 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = { + pkh : Signature.Public_key_hash.t; + pk : Signature.Public_key.t; + sk : Signature.Secret_key.t; +} + +type account = t + +let known_accounts = Signature.Public_key_hash.Table.create 17 + +let new_account ?seed () = + let (pkh, pk, sk) = Signature.generate_key ?seed () in + let account = {pkh; pk; sk} in + Signature.Public_key_hash.Table.add known_accounts pkh account ; + account + +let add_account ({pkh; _} as account) = + Signature.Public_key_hash.Table.add known_accounts pkh account + +let activator_account = new_account () + +let find pkh = + match Signature.Public_key_hash.Table.find known_accounts pkh with + | Some k -> + return k + | None -> + failwith "Missing account: %a" Signature.Public_key_hash.pp pkh + +let find_alternate pkh = + let exception Found of t in + try + Signature.Public_key_hash.Table.iter + (fun pkh' account -> + if not (Signature.Public_key_hash.equal pkh pkh') then + raise (Found account)) + known_accounts ; + raise Not_found + with Found account -> account + +let dummy_account = new_account () + +let generate_accounts ?(initial_balances = []) n : (t * Tez.t) list = + Signature.Public_key_hash.Table.clear known_accounts ; + let default_amount = Tez.of_mutez_exn 4_000_000_000_000L in + let amount i = + match List.nth_opt initial_balances i with + | None -> + default_amount + | Some a -> + Tez.of_mutez_exn a + in + List.map + (fun i -> + let (pkh, pk, sk) = Signature.generate_key () in + let account = {pkh; pk; sk} in + Signature.Public_key_hash.Table.add known_accounts pkh account ; + (account, amount i)) + (0 -- (n - 1)) + +let commitment_secret = + Blinded_public_key_hash.activation_code_of_hex + "aaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb" + +let new_commitment ?seed () = + let (pkh, pk, sk) = Signature.generate_key ?seed ~algo:Ed25519 () in + let unactivated_account = {pkh; pk; sk} in + let open Commitment in + let pkh = match pkh with Ed25519 pkh -> pkh | _ -> assert false in + let bpkh = Blinded_public_key_hash.of_ed25519_pkh commitment_secret pkh in + Lwt.return + ( (Environment.wrap_tzresult @@ Tez.(one *? 4_000L)) + >|? fun amount -> + (unactivated_account, {blinded_public_key_hash = bpkh; amount}) ) diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/account.mli b/src/proto_009_PsFLoren/lib_protocol/test/helpers/account.mli new file mode 100644 index 0000000000000000000000000000000000000000..b39fb7d0d2310e0289d0d583d82114f7c9854210 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/account.mli @@ -0,0 +1,61 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = { + pkh : Signature.Public_key_hash.t; + pk : Signature.Public_key.t; + sk : Signature.Secret_key.t; +} + +type account = t + +val known_accounts : t Signature.Public_key_hash.Table.t + +val activator_account : account + +val dummy_account : account + +val new_account : ?seed:Bytes.t -> unit -> account + +val add_account : t -> unit + +val find : Signature.Public_key_hash.t -> t tzresult Lwt.t + +val find_alternate : Signature.Public_key_hash.t -> t + +(** [generate_accounts ?initial_balances n] : generates [n] random + accounts with the initial balance of the [i]th account given by the + [i]th value in the list [initial_balances] or otherwise + 4.000.000.000 tz (if the list is too short); and add them to the + global account state *) +val generate_accounts : ?initial_balances:int64 list -> int -> (t * Tez.t) list + +val commitment_secret : Blinded_public_key_hash.activation_code + +val new_commitment : + ?seed:Bytes.t -> unit -> (account * Commitment.t) tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/assert.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/assert.ml new file mode 100644 index 0000000000000000000000000000000000000000..7ef41cd65766d99ce5a539ee04655d216475f1d6 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/assert.ml @@ -0,0 +1,132 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +let error ~loc v f = + match v with + | Error err when List.exists f err -> + return_unit + | Ok _ -> + failwith "Unexpected successful result (%s)" loc + | Error err -> + failwith "@[Unexpected error (%s): %a@]" loc pp_print_error err + +let proto_error ~loc v f = + error ~loc v (function + | Environment.Ecoproto_error err -> + f err + | _ -> + false) + +let equal ~loc (cmp : 'a -> 'a -> bool) msg pp a b = + if not (cmp a b) then + failwith "@[@[[%s]@] - @[%s : %a is not equal to %a@]@]" loc msg pp a pp b + else return_unit + +let not_equal ~loc (cmp : 'a -> 'a -> bool) msg pp a b = + if cmp a b then + failwith "@[@[[%s]@] - @[%s : %a is equal to %a@]@]" loc msg pp a pp b + else return_unit + +(* tez *) +let equal_tez ~loc (a : Alpha_context.Tez.t) (b : Alpha_context.Tez.t) = + let open Alpha_context in + equal ~loc Tez.( = ) "Tez aren't equal" Tez.pp a b + +let not_equal_tez ~loc (a : Alpha_context.Tez.t) (b : Alpha_context.Tez.t) = + let open Alpha_context in + not_equal ~loc Tez.( = ) "Tez are equal" Tez.pp a b + +(* int *) +let equal_int ~loc (a : int) (b : int) = + equal ~loc ( = ) "Integers aren't equal" Format.pp_print_int a b + +let not_equal_int ~loc (a : int) (b : int) = + not_equal ~loc ( = ) "Integers are equal" Format.pp_print_int a b + +(* bool *) +let equal_bool ~loc (a : bool) (b : bool) = + equal ~loc ( = ) "Booleans aren't equal" Format.pp_print_bool a b + +let not_equal_bool ~loc (a : bool) (b : bool) = + not_equal ~loc ( = ) "Booleans are equal" Format.pp_print_bool a b + +(* pkh *) +let equal_pkh ~loc (a : Signature.Public_key_hash.t) + (b : Signature.Public_key_hash.t) = + let module PKH = Signature.Public_key_hash in + equal ~loc PKH.equal "Public key hashes aren't equal" PKH.pp a b + +let not_equal_pkh ~loc (a : Signature.Public_key_hash.t) + (b : Signature.Public_key_hash.t) = + let module PKH = Signature.Public_key_hash in + not_equal ~loc PKH.equal "Public key hashes are equal" PKH.pp a b + +open Context + +(* Some asserts for account operations *) + +(** [balance_is b c amount] checks that the current balance of contract [c] is + [amount]. + Default balance type is [Main], pass [~kind] with [Deposit], [Fees] or + [Rewards] for the others. *) +let balance_is ~loc b contract ?(kind = Contract.Main) expected = + Contract.balance b contract ~kind + >>=? fun balance -> equal_tez ~loc balance expected + +(** [balance_was_operated ~operand b c old_balance amount] checks that the + current balance of contract [c] is [operand old_balance amount] and + returns the current balance. + Default balance type is [Main], pass [~kind] with [Deposit], [Fees] or + [Rewards] for the others. *) +let balance_was_operated ~operand ~loc b contract ?(kind = Contract.Main) + old_balance amount = + operand old_balance amount |> Environment.wrap_tzresult + >>?= fun expected -> balance_is ~loc b contract ~kind expected + +let balance_was_credited = + balance_was_operated ~operand:Alpha_context.Tez.( +? ) + +let balance_was_debited = + balance_was_operated ~operand:Alpha_context.Tez.( -? ) + +(* debug *) + +let print_balances ctxt id = + Contract.balance ~kind:Main ctxt id + >>=? fun main -> + Contract.balance ~kind:Deposit ctxt id + >>=? fun deposit -> + Contract.balance ~kind:Fees ctxt id + >>=? fun fees -> + Contract.balance ~kind:Rewards ctxt id + >|=? fun rewards -> + Format.printf + "\nMain: %s\nDeposit: %s\nFees: %s\nRewards: %s\n" + (Alpha_context.Tez.to_string main) + (Alpha_context.Tez.to_string deposit) + (Alpha_context.Tez.to_string fees) + (Alpha_context.Tez.to_string rewards) diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/block.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/block.ml new file mode 100644 index 0000000000000000000000000000000000000000..be8f56092131495e95df30f2ca92f0746a8eb30b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/block.ml @@ -0,0 +1,445 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +module Proto_Nonce = Nonce (* Renamed otherwise is masked by Alpha_context *) + +open Alpha_context + +(* This type collects a block and the context that results from its application *) +type t = { + hash : Block_hash.t; + header : Block_header.t; + operations : Operation.packed list; + context : Tezos_protocol_environment.Context.t; +} + +type block = t + +let rpc_context block = + { + Environment.Updater.block_hash = block.hash; + block_header = block.header.shell; + context = block.context; + } + +let rpc_ctxt = + new Environment.proto_rpc_context_of_directory rpc_context rpc_services + +(******** Policies ***********) + +(* Policies are functions that take a block and return a tuple + [(account, level, timestamp)] for the [forge_header] function. *) + +(* This type is used only to provide a simpler interface to the exterior. *) +type baker_policy = + | By_priority of int + | By_account of public_key_hash + | Excluding of public_key_hash list + +let get_next_baker_by_priority priority block = + Alpha_services.Delegate.Baking_rights.get + rpc_ctxt + ~all:true + ~max_priority:(priority + 1) + block + >|=? fun bakers -> + let {Alpha_services.Delegate.Baking_rights.delegate = pkh; timestamp; _} = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun {Alpha_services.Delegate.Baking_rights.priority = p; _} -> + p = priority) + bakers + in + (pkh, priority, WithExceptions.Option.to_exn ~none:(Failure "") timestamp) + +let get_next_baker_by_account pkh block = + Alpha_services.Delegate.Baking_rights.get + rpc_ctxt + ~delegates:[pkh] + ~max_priority:256 + block + >|=? fun bakers -> + let { Alpha_services.Delegate.Baking_rights.delegate = pkh; + timestamp; + priority; + _ } = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bakers + in + (pkh, priority, WithExceptions.Option.to_exn ~none:(Failure "") timestamp) + +let get_next_baker_excluding excludes block = + Alpha_services.Delegate.Baking_rights.get rpc_ctxt ~max_priority:256 block + >|=? fun bakers -> + let { Alpha_services.Delegate.Baking_rights.delegate = pkh; + timestamp; + priority; + _ } = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun {Alpha_services.Delegate.Baking_rights.delegate; _} -> + not (List.mem delegate excludes)) + bakers + in + (pkh, priority, WithExceptions.Option.to_exn ~none:(Failure "") timestamp) + +let dispatch_policy = function + | By_priority p -> + get_next_baker_by_priority p + | By_account a -> + get_next_baker_by_account a + | Excluding al -> + get_next_baker_excluding al + +let get_next_baker ?(policy = By_priority 0) = dispatch_policy policy + +let get_endorsing_power b = + List.fold_left_es + (fun acc (op : Operation.packed) -> + let (Operation_data data) = op.protocol_data in + match data.contents with + | Single (Endorsement _) -> + Alpha_services.Delegate.Endorsing_power.get + rpc_ctxt + b + op + Chain_id.zero + >|=? fun endorsement_power -> acc + endorsement_power + | _ -> + return acc) + 0 + b.operations + +module Forge = struct + type header = { + baker : public_key_hash; + (* the signer of the block *) + shell : Block_header.shell_header; + contents : Block_header.contents; + } + + let default_proof_of_work_nonce = + Bytes.create Constants.proof_of_work_nonce_size + + let make_contents ?(proof_of_work_nonce = default_proof_of_work_nonce) + ~priority ~seed_nonce_hash () = + Block_header.{priority; proof_of_work_nonce; seed_nonce_hash} + + let make_shell ~level ~predecessor ~timestamp ~fitness ~operations_hash = + Tezos_base.Block_header. + { + level; + predecessor; + timestamp; + fitness; + operations_hash; + (* We don't care of the following values, only the shell validates them. *) + proto_level = 0; + validation_passes = 0; + context = Context_hash.zero; + } + + let set_seed_nonce_hash seed_nonce_hash {baker; shell; contents} = + {baker; shell; contents = {contents with seed_nonce_hash}} + + let set_baker baker header = {header with baker} + + let sign_header {baker; shell; contents} = + Account.find baker + >|=? fun delegate -> + let unsigned_bytes = + Data_encoding.Binary.to_bytes_exn + Block_header.unsigned_encoding + (shell, contents) + in + let signature = + Signature.sign + ~watermark:Signature.(Block_header Chain_id.zero) + delegate.sk + unsigned_bytes + in + Block_header.{shell; protocol_data = {contents; signature}} + + let forge_header ?(policy = By_priority 0) ?timestamp ?(operations = []) pred + = + dispatch_policy policy pred + >>=? fun (pkh, priority, _timestamp) -> + Alpha_services.Delegate.Minimal_valid_time.get rpc_ctxt pred priority 0 + >>=? fun expected_timestamp -> + let timestamp = Option.value ~default:expected_timestamp timestamp in + let level = Int32.succ pred.header.shell.level in + ( match Fitness.to_int64 pred.header.shell.fitness with + | Ok old_fitness -> + Fitness.from_int64 (Int64.add (Int64.of_int 1) old_fitness) + | Error _ -> + assert false ) + |> fun fitness -> + Alpha_services.Helpers.current_level ~offset:1l rpc_ctxt pred + >|=? (function + | {expected_commitment = true; _} -> + Some (fst (Proto_Nonce.generate ())) + | {expected_commitment = false; _} -> + None) + >|=? fun seed_nonce_hash -> + let hashes = List.map Operation.hash_packed operations in + let operations_hash = + Operation_list_list_hash.compute [Operation_list_hash.compute hashes] + in + let shell = + make_shell + ~level + ~predecessor:pred.hash + ~timestamp + ~fitness + ~operations_hash + in + let contents = make_contents ~priority ~seed_nonce_hash () in + {baker = pkh; shell; contents} + + (* compatibility only, needed by incremental *) + let contents ?(proof_of_work_nonce = default_proof_of_work_nonce) + ?(priority = 0) ?seed_nonce_hash () = + {Block_header.priority; proof_of_work_nonce; seed_nonce_hash} +end + +(********* Genesis creation *************) + +(* Hard-coded context key *) +let protocol_param_key = ["protocol_parameters"] + +let check_constants_consistency constants = + let open Constants in + let {blocks_per_cycle; blocks_per_commitment; blocks_per_roll_snapshot; _} = + constants + in + Error_monad.unless (blocks_per_commitment <= blocks_per_cycle) (fun () -> + failwith + "Inconsistent constants : blocks per commitment must be less than \ + blocks per cycle") + >>=? fun () -> + Error_monad.unless (blocks_per_cycle >= blocks_per_roll_snapshot) (fun () -> + failwith + "Inconsistent constants : blocks per cycle must be superior than \ + blocks per roll snapshot") + +let initial_context ?(with_commitments = false) constants header + initial_accounts = + let open Tezos_protocol_009_PsFLoren_parameters in + let bootstrap_accounts = + List.map + (fun (Account.{pk; pkh; _}, amount) -> + Default_parameters.make_bootstrap_account (pkh, pk, amount)) + initial_accounts + in + let parameters = + Default_parameters.parameters_of_constants + ~bootstrap_accounts + ~with_commitments + constants + in + let json = Default_parameters.json_of_parameters parameters in + let proto_params = + Data_encoding.Binary.to_bytes_exn Data_encoding.json json + in + Tezos_protocol_environment.Context.( + let empty = Memory_context.empty in + add empty ["version"] (Bytes.of_string "genesis") + >>= fun ctxt -> add ctxt protocol_param_key proto_params) + >>= fun ctxt -> + Main.init ctxt header >|= Environment.wrap_tzresult + >|=? fun {context; _} -> context + +let genesis_with_parameters parameters = + let hash = + Block_hash.of_b58check_exn + "BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU" + in + let shell = + Forge.make_shell + ~level:0l + ~predecessor:hash + ~timestamp:Time.Protocol.epoch + ~fitness:(Fitness.from_int64 0L) + ~operations_hash:Operation_list_list_hash.zero + in + let contents = Forge.make_contents ~priority:0 ~seed_nonce_hash:None () in + let open Tezos_protocol_009_PsFLoren_parameters in + let json = Default_parameters.json_of_parameters parameters in + let proto_params = + Data_encoding.Binary.to_bytes_exn Data_encoding.json json + in + Tezos_protocol_environment.Context.( + let empty = Memory_context.empty in + add empty ["version"] (Bytes.of_string "genesis") + >>= fun ctxt -> add ctxt protocol_param_key proto_params) + >>= fun ctxt -> + Main.init ctxt shell >|= Environment.wrap_tzresult + >|=? fun {context; _} -> + { + hash; + header = {shell; protocol_data = {contents; signature = Signature.zero}}; + operations = []; + context; + } + +(* if no parameter file is passed we check in the current directory + where the test is run *) +let genesis ?with_commitments ?endorsers_per_block ?initial_endorsers + ?min_proposal_quorum (initial_accounts : (Account.t * Tez.t) list) = + if initial_accounts = [] then + Stdlib.failwith "Must have one account with a roll to bake" ; + let open Tezos_protocol_009_PsFLoren_parameters in + let constants = Default_parameters.constants_test in + let endorsers_per_block = + Option.value ~default:constants.endorsers_per_block endorsers_per_block + in + let initial_endorsers = + Option.value ~default:constants.initial_endorsers initial_endorsers + in + let min_proposal_quorum = + Option.value ~default:constants.min_proposal_quorum min_proposal_quorum + in + let constants = + { + constants with + endorsers_per_block; + initial_endorsers; + min_proposal_quorum; + } + in + (* Check there is at least one roll *) + Lwt.catch + (fun () -> + List.fold_left_es + (fun acc (_, amount) -> + Environment.wrap_tzresult @@ Tez.( +? ) acc amount + >>?= fun acc -> + if acc >= constants.tokens_per_roll then raise Exit else return acc) + Tez.zero + initial_accounts + >>=? fun _ -> + failwith "Insufficient tokens in initial accounts to create one roll") + (function Exit -> return_unit | exc -> raise exc) + >>=? fun () -> + check_constants_consistency constants + >>=? fun () -> + let hash = + Block_hash.of_b58check_exn + "BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU" + in + let shell = + Forge.make_shell + ~level:0l + ~predecessor:hash + ~timestamp:Time.Protocol.epoch + ~fitness:(Fitness.from_int64 0L) + ~operations_hash:Operation_list_list_hash.zero + in + let contents = Forge.make_contents ~priority:0 ~seed_nonce_hash:None () in + initial_context ?with_commitments constants shell initial_accounts + >|=? fun context -> + { + hash; + header = {shell; protocol_data = {contents; signature = Signature.zero}}; + operations = []; + context; + } + +(********* Baking *************) + +let apply header ?(operations = []) pred = + (let open Environment.Error_monad in + Main.begin_application + ~chain_id:Chain_id.zero + ~predecessor_context:pred.context + ~predecessor_fitness:pred.header.shell.fitness + ~predecessor_timestamp:pred.header.shell.timestamp + header + >>=? fun vstate -> + List.fold_left_es + (fun vstate op -> + apply_operation vstate op >|=? fun (state, _result) -> state) + vstate + operations + >>=? fun vstate -> + Main.finalize_block vstate + >|=? fun (validation, _result) -> validation.context) + >|= Environment.wrap_tzresult + >|=? fun context -> + let hash = Block_header.hash header in + {hash; header; operations; context} + +let bake ?policy ?timestamp ?operation ?operations pred = + let operations = + match (operation, operations) with + | (Some op, Some ops) -> + Some (op :: ops) + | (Some op, None) -> + Some [op] + | (None, Some ops) -> + Some ops + | (None, None) -> + None + in + Forge.forge_header ?timestamp ?policy ?operations pred + >>=? fun header -> + Forge.sign_header header >>=? fun header -> apply header ?operations pred + +(********** Cycles ****************) + +(* This function is duplicated from Context to avoid a cyclic dependency *) +let get_constants b = Alpha_services.Constants.all rpc_ctxt b + +let bake_n ?policy n b = + List.fold_left_es (fun b _ -> bake ?policy b) b (1 -- n) + +let bake_until_cycle_end ?policy b = + get_constants b + >>=? fun Constants.{parametric = {blocks_per_cycle; _}; _} -> + let current_level = b.header.shell.level in + let current_level = Int32.rem current_level blocks_per_cycle in + let delta = Int32.sub blocks_per_cycle current_level in + bake_n ?policy (Int32.to_int delta) b + +let bake_until_n_cycle_end ?policy n b = + List.fold_left_es (fun b _ -> bake_until_cycle_end ?policy b) b (1 -- n) + +let current_cycle b = + get_constants b + >>=? fun Constants.{parametric = {blocks_per_cycle; _}; _} -> + let current_level = b.header.shell.level in + let current_cycle = Int32.div current_level blocks_per_cycle in + let current_cycle = Cycle.add Cycle.root (Int32.to_int current_cycle) in + return current_cycle + +let bake_until_cycle ?policy cycle (b : t) = + let rec loop (b : t) = + current_cycle b + >>=? fun current_cycle -> + if Cycle.equal cycle current_cycle then return b + else bake_until_cycle_end ?policy b >>=? fun b -> loop b + in + loop b diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/block.mli b/src/proto_009_PsFLoren/lib_protocol/test/helpers/block.mli new file mode 100644 index 0000000000000000000000000000000000000000..7d327b3fdf99544d227001c18d150ac74a6e9a4b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/block.mli @@ -0,0 +1,142 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = { + hash : Block_hash.t; + header : Block_header.t; + operations : Operation.packed list; + context : Tezos_protocol_environment.Context.t; (** Resulting context *) +} + +type block = t + +val rpc_ctxt : t Environment.RPC_context.simple + +(** Policies to select the next baker: + - [By_priority p] selects the baker at priority [p] + - [By_account pkh] selects the first slot for baker [pkh] + - [Excluding pkhs] selects the first baker that doesn't belong to [pkhs] +*) +type baker_policy = + | By_priority of int + | By_account of public_key_hash + | Excluding of public_key_hash list + +(** Returns (account, priority, timestamp) of the next baker given + a policy, defaults to By_priority 0. *) +val get_next_baker : + ?policy:baker_policy -> + t -> + (public_key_hash * int * Time.Protocol.t) tzresult Lwt.t + +val get_endorsing_power : block -> int tzresult Lwt.t + +module Forge : sig + val contents : + ?proof_of_work_nonce:Bytes.t -> + ?priority:int -> + ?seed_nonce_hash:Nonce_hash.t -> + unit -> + Block_header.contents + + type header + + (** Forges a correct header following the policy. + The header can then be modified and applied with [apply]. *) + val forge_header : + ?policy:baker_policy -> + ?timestamp:Timestamp.time -> + ?operations:Operation.packed list -> + t -> + header tzresult Lwt.t + + (** Sets uniquely seed_nonce_hash of a header *) + val set_seed_nonce_hash : Nonce_hash.t option -> header -> header + + (** Sets the baker that will sign the header to an arbitrary pkh *) + val set_baker : public_key_hash -> header -> header + + (** Signs the header with the key of the baker configured in the header. + The header can no longer be modified, only applied. *) + val sign_header : header -> Block_header.block_header tzresult Lwt.t +end + +(** [genesis accounts] : generates an initial block with the + given constants [] and initializes [accounts] with their + associated amounts. +*) +val genesis : + ?with_commitments:bool -> + ?endorsers_per_block:int -> + ?initial_endorsers:int -> + ?min_proposal_quorum:int32 -> + (Account.t * Tez.tez) list -> + block tzresult Lwt.t + +val genesis_with_parameters : Parameters.t -> block tzresult Lwt.t + +(** Applies a signed header and its operations to a block and + obtains a new block *) +val apply : + Block_header.block_header -> + ?operations:Operation.packed list -> + t -> + t tzresult Lwt.t + +(** + [bake b] returns a block [b'] which has as predecessor block [b]. + Optional parameter [policy] allows to pick the next baker in several ways. + This function bundles together [forge_header], [sign_header] and [apply]. + These functions should be used instead of bake to craft unusual blocks for + testing together with setters for properties of the headers. + For examples see seed.ml or double_baking.ml +*) +val bake : + ?policy:baker_policy -> + ?timestamp:Timestamp.time -> + ?operation:Operation.packed -> + ?operations:Operation.packed list -> + t -> + t tzresult Lwt.t + +(** Bakes [n] blocks. *) +val bake_n : ?policy:baker_policy -> int -> t -> block tzresult Lwt.t + +val current_cycle : t -> Cycle.t tzresult Lwt.t + +(** Given a block [b] at level [l] bakes enough blocks to complete a cycle, + that is [blocks_per_cycle - (l % blocks_per_cycle)]. *) +val bake_until_cycle_end : ?policy:baker_policy -> t -> t tzresult Lwt.t + +(** Bakes enough blocks to end [n] cycles. *) +val bake_until_n_cycle_end : + ?policy:baker_policy -> int -> t -> t tzresult Lwt.t + +(** Bakes enough blocks to reach the cycle. *) +val bake_until_cycle : ?policy:baker_policy -> Cycle.t -> t -> t tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/context.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/context.ml new file mode 100644 index 0000000000000000000000000000000000000000..7b18159b68a34d679be02299be7914a46c4ffb20 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/context.ml @@ -0,0 +1,309 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = B of Block.t | I of Incremental.t + +let branch = function B b -> b.hash | I i -> (Incremental.predecessor i).hash + +let level = function B b -> b.header.shell.level | I i -> Incremental.level i + +let get_level ctxt = + level ctxt |> Raw_level.of_int32 |> Environment.wrap_tzresult + +let rpc_ctxt = + object + method call_proto_service0 + : 'm 'q 'i 'o. + ( ([< RPC_service.meth] as 'm), + Environment.RPC_context.t, + Environment.RPC_context.t, + 'q, + 'i, + 'o ) + RPC_service.t -> t -> 'q -> 'i -> 'o tzresult Lwt.t = + fun s pr q i -> + match pr with + | B b -> + Block.rpc_ctxt#call_proto_service0 s b q i + | I b -> + Incremental.rpc_ctxt#call_proto_service0 s b q i + + method call_proto_service1 + : 'm 'a 'q 'i 'o. + ( ([< RPC_service.meth] as 'm), + Environment.RPC_context.t, + Environment.RPC_context.t * 'a, + 'q, + 'i, + 'o ) + RPC_service.t -> t -> 'a -> 'q -> 'i -> 'o tzresult Lwt.t = + fun s pr a q i -> + match pr with + | B bl -> + Block.rpc_ctxt#call_proto_service1 s bl a q i + | I bl -> + Incremental.rpc_ctxt#call_proto_service1 s bl a q i + + method call_proto_service2 + : 'm 'a 'b 'q 'i 'o. + ( ([< RPC_service.meth] as 'm), + Environment.RPC_context.t, + (Environment.RPC_context.t * 'a) * 'b, + 'q, + 'i, + 'o ) + RPC_service.t -> t -> 'a -> 'b -> 'q -> 'i -> 'o tzresult Lwt.t = + fun s pr a b q i -> + match pr with + | B bl -> + Block.rpc_ctxt#call_proto_service2 s bl a b q i + | I bl -> + Incremental.rpc_ctxt#call_proto_service2 s bl a b q i + + method call_proto_service3 + : 'm 'a 'b 'c 'q 'i 'o. + ( ([< RPC_service.meth] as 'm), + Environment.RPC_context.t, + ((Environment.RPC_context.t * 'a) * 'b) * 'c, + 'q, + 'i, + 'o ) + RPC_service.t -> t -> 'a -> 'b -> 'c -> 'q -> 'i -> 'o tzresult Lwt.t + = + fun s pr a b c q i -> + match pr with + | B bl -> + Block.rpc_ctxt#call_proto_service3 s bl a b c q i + | I bl -> + Incremental.rpc_ctxt#call_proto_service3 s bl a b c q i + end + +let get_endorsers ctxt = + Alpha_services.Delegate.Endorsing_rights.get rpc_ctxt ctxt + +let get_endorser ctxt = + Alpha_services.Delegate.Endorsing_rights.get rpc_ctxt ctxt + >|=? fun endorsers -> + let endorser = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd endorsers in + (endorser.delegate, endorser.slots) + +let get_voting_power = Alpha_services.Delegate.voting_power rpc_ctxt + +let get_total_voting_power = Alpha_services.Voting.total_voting_power rpc_ctxt + +let get_bakers ctxt = + Alpha_services.Delegate.Baking_rights.get ~max_priority:256 rpc_ctxt ctxt + >|=? fun bakers -> + List.map (fun p -> p.Alpha_services.Delegate.Baking_rights.delegate) bakers + +let get_seed_nonce_hash ctxt = + let header = + match ctxt with B {header; _} -> header | I i -> Incremental.header i + in + match header.protocol_data.contents.seed_nonce_hash with + | None -> + failwith "No committed nonce" + | Some hash -> + return hash + +let get_seed ctxt = Alpha_services.Seed.get rpc_ctxt ctxt + +let get_constants ctxt = Alpha_services.Constants.all rpc_ctxt ctxt + +let get_minimal_valid_time ctxt ~priority ~endorsing_power = + Alpha_services.Delegate.Minimal_valid_time.get + rpc_ctxt + ctxt + priority + endorsing_power + +let rec reward_for_priority reward_per_prio prio = + match reward_per_prio with + | [] -> + (* Empty reward list in parameters means no rewards *) + Tez.zero + | [last] -> + last + | first :: rest -> + if Compare.Int.(prio <= 0) then first + else reward_for_priority rest (pred prio) + +let get_baking_reward ctxt ~priority ~endorsing_power = + get_constants ctxt + >>=? fun {Constants.parametric = {baking_reward_per_endorsement; _}; _} -> + let reward_per_endorsement = + reward_for_priority baking_reward_per_endorsement priority + in + Lwt.return + (Environment.wrap_tzresult + Tez.(reward_per_endorsement *? Int64.of_int endorsing_power)) + +let get_endorsing_reward ctxt ~priority ~endorsing_power = + get_constants ctxt + >>=? fun {Constants.parametric = {endorsement_reward; _}; _} -> + let reward_per_endorsement = + reward_for_priority endorsement_reward priority + in + Lwt.return + (Environment.wrap_tzresult + Tez.(reward_per_endorsement *? Int64.of_int endorsing_power)) + +(* Voting *) + +module Vote = struct + let get_ballots ctxt = Alpha_services.Voting.ballots rpc_ctxt ctxt + + let get_ballot_list ctxt = Alpha_services.Voting.ballot_list rpc_ctxt ctxt + + let get_current_period ctxt = + Alpha_services.Voting.current_period rpc_ctxt ctxt + + let get_current_quorum ctxt = + Alpha_services.Voting.current_quorum rpc_ctxt ctxt + + let get_listings ctxt = Alpha_services.Voting.listings rpc_ctxt ctxt + + let get_proposals ctxt = Alpha_services.Voting.proposals rpc_ctxt ctxt + + let get_current_proposal ctxt = + Alpha_services.Voting.current_proposal rpc_ctxt ctxt + + let get_protocol (b : Block.t) = + Tezos_protocol_environment.Context.get_protocol b.context + + let get_participation_ema (b : Block.t) = + Environment.Context.find b.context ["votes"; "participation_ema"] + >|= function + | None -> assert false | Some bytes -> ok (TzEndian.get_int32 bytes 0) + + let set_participation_ema (b : Block.t) ema = + let bytes = Bytes.make 4 '\000' in + TzEndian.set_int32 bytes 0 ema ; + Environment.Context.add b.context ["votes"; "participation_ema"] bytes + >|= fun context -> {b with context} +end + +module Contract = struct + let pp = Alpha_context.Contract.pp + + let pkh c = + Alpha_context.Contract.is_implicit c + |> function + | Some p -> return p | None -> failwith "pkh: only for implicit contracts" + + type balance_kind = Main | Deposit | Fees | Rewards + + let balance ?(kind = Main) ctxt contract = + match kind with + | Main -> + Alpha_services.Contract.balance rpc_ctxt ctxt contract + | _ -> ( + match Alpha_context.Contract.is_implicit contract with + | None -> + invalid_arg + "get_balance: no frozen accounts for an originated contract." + | Some pkh -> + Alpha_services.Delegate.frozen_balance_by_cycle rpc_ctxt ctxt pkh + >>=? fun map -> + Lwt.return + @@ Cycle.Map.fold + (fun _cycle {Delegate.deposit; fees; rewards} acc -> + acc + >>? fun acc -> + match kind with + | Deposit -> + Test_tez.Tez.(acc +? deposit) + | Fees -> + Test_tez.Tez.(acc +? fees) + | Rewards -> + Test_tez.Tez.(acc +? rewards) + | _ -> + assert false) + map + (Ok Tez.zero) ) + + let counter ctxt contract = + match Contract.is_implicit contract with + | None -> + invalid_arg "Helpers.Context.counter" + | Some mgr -> + Alpha_services.Contract.counter rpc_ctxt ctxt mgr + + let manager _ contract = + match Contract.is_implicit contract with + | None -> + invalid_arg "Helpers.Context.manager" + | Some pkh -> + Account.find pkh + + let is_manager_key_revealed ctxt contract = + match Contract.is_implicit contract with + | None -> + invalid_arg "Helpers.Context.is_manager_key_revealed" + | Some mgr -> + Alpha_services.Contract.manager_key rpc_ctxt ctxt mgr + >|=? fun res -> res <> None + + let delegate ctxt contract = + Alpha_services.Contract.delegate rpc_ctxt ctxt contract + + let delegate_opt ctxt contract = + Alpha_services.Contract.delegate_opt rpc_ctxt ctxt contract +end + +module Delegate = struct + type info = Delegate_services.info = { + balance : Tez.t; + frozen_balance : Tez.t; + frozen_balance_by_cycle : Delegate.frozen_balance Cycle.Map.t; + staking_balance : Tez.t; + delegated_contracts : Alpha_context.Contract.t list; + delegated_balance : Tez.t; + deactivated : bool; + grace_period : Cycle.t; + voting_power : int32; + } + + let info ctxt pkh = Alpha_services.Delegate.info rpc_ctxt ctxt pkh +end + +let init ?endorsers_per_block ?with_commitments ?(initial_balances = []) + ?initial_endorsers ?min_proposal_quorum n = + let accounts = Account.generate_accounts ~initial_balances n in + let contracts = + List.map + (fun (a, _) -> Alpha_context.Contract.implicit_contract Account.(a.pkh)) + accounts + in + Block.genesis + ?endorsers_per_block + ?with_commitments + ?initial_endorsers + ?min_proposal_quorum + accounts + >|=? fun blk -> (blk, contracts) diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/context.mli b/src/proto_009_PsFLoren/lib_protocol/test/helpers/context.mli new file mode 100644 index 0000000000000000000000000000000000000000..1a21dcd7cc92cd9a1b7b9cf050474f476d85c300 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/context.mli @@ -0,0 +1,138 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Environment + +type t = B of Block.t | I of Incremental.t + +val branch : t -> Block_hash.t + +val get_level : t -> Raw_level.t tzresult + +val get_endorsers : + t -> Alpha_services.Delegate.Endorsing_rights.t list tzresult Lwt.t + +val get_endorser : t -> (public_key_hash * int list) tzresult Lwt.t + +val get_voting_power : + t -> public_key_hash -> int32 Environment.Error_monad.shell_tzresult Lwt.t + +val get_total_voting_power : + t -> int32 Environment.Error_monad.shell_tzresult Lwt.t + +val get_bakers : t -> public_key_hash list tzresult Lwt.t + +val get_seed_nonce_hash : t -> Nonce_hash.t tzresult Lwt.t + +(** Returns the seed of the cycle to which the block belongs to. *) +val get_seed : t -> Seed.seed tzresult Lwt.t + +(** Returns all the constants of the protocol *) +val get_constants : t -> Constants.t tzresult Lwt.t + +val get_minimal_valid_time : + t -> priority:int -> endorsing_power:int -> Time.t tzresult Lwt.t + +val get_baking_reward : + t -> priority:int -> endorsing_power:int -> Tez.t tzresult Lwt.t + +val get_endorsing_reward : + t -> priority:int -> endorsing_power:int -> Tez.t tzresult Lwt.t + +module Vote : sig + val get_ballots : t -> Vote.ballots tzresult Lwt.t + + val get_ballot_list : + t -> (Signature.Public_key_hash.t * Vote.ballot) list tzresult Lwt.t + + val get_current_period : t -> Voting_period.info tzresult Lwt.t + + val get_current_quorum : t -> int32 tzresult Lwt.t + + val get_participation_ema : Block.t -> int32 tzresult Lwt.t + + val get_listings : + t -> (Signature.Public_key_hash.t * int32) list tzresult Lwt.t + + val get_proposals : t -> int32 Protocol_hash.Map.t tzresult Lwt.t + + val get_current_proposal : t -> Protocol_hash.t option tzresult Lwt.t + + val get_protocol : Block.t -> Protocol_hash.t Lwt.t + + val set_participation_ema : Block.t -> int32 -> Block.t Lwt.t +end + +module Contract : sig + val pp : Format.formatter -> Contract.t -> unit + + val pkh : Contract.t -> public_key_hash tzresult Lwt.t + + type balance_kind = Main | Deposit | Fees | Rewards + + (** Returns the balance of a contract, by default the main balance. + If the contract is implicit the frozen balances are available too: + deposit, fees or rewards. *) + val balance : ?kind:balance_kind -> t -> Contract.t -> Tez.t tzresult Lwt.t + + val counter : t -> Contract.t -> Z.t tzresult Lwt.t + + val manager : t -> Contract.t -> Account.t tzresult Lwt.t + + val is_manager_key_revealed : t -> Contract.t -> bool tzresult Lwt.t + + val delegate : t -> Contract.t -> public_key_hash tzresult Lwt.t + + val delegate_opt : t -> Contract.t -> public_key_hash option tzresult Lwt.t +end + +module Delegate : sig + type info = Delegate_services.info = { + balance : Tez.t; + frozen_balance : Tez.t; + frozen_balance_by_cycle : Delegate.frozen_balance Cycle.Map.t; + staking_balance : Tez.t; + delegated_contracts : Alpha_context.Contract.t list; + delegated_balance : Tez.t; + deactivated : bool; + grace_period : Cycle.t; + voting_power : int32; + } + + val info : t -> public_key_hash -> Delegate_services.info tzresult Lwt.t +end + +(** [init n] : returns an initial block with [n] initialized accounts + and the associated implicit contracts *) +val init : + ?endorsers_per_block:int -> + ?with_commitments:bool -> + ?initial_balances:int64 list -> + ?initial_endorsers:int -> + ?min_proposal_quorum:int32 -> + int -> + (Block.t * Alpha_context.Contract.t list) tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/dune b/src/proto_009_PsFLoren/lib_protocol/test/helpers/dune new file mode 100644 index 0000000000000000000000000000000000000000..673c400f93a5e0d8168e00a6fce1e9d77440a8d7 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/dune @@ -0,0 +1,23 @@ +(library + (name tezos_009_PsFLoren_test_helpers) + (public_name tezos-009-PsFLoren-test-helpers) + (libraries alcotest-lwt + tezos-base + tezos-stdlib-unix + tezos-shell-services + tezos-protocol-environment + tezos-protocol-009-PsFLoren + tezos-protocol-009-PsFLoren-parameters + tezos-client-009-PsFLoren) + (flags (:standard -open Tezos_base__TzPervasives + -open Tezos_micheline + -open Tezos_stdlib_unix + -open Tezos_protocol_009_PsFLoren + -open Tezos_client_009_PsFLoren + -open Tezos_protocol_environment_009_PsFLoren + -open Tezos_shell_services))) + +(rule + (alias runtest_lint) + (deps (glob_files *.ml{,i})) + (action (run %{lib:tezos-tooling:lint.sh} %{deps}))) diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/dune-project b/src/proto_009_PsFLoren/lib_protocol/test/helpers/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..cbae350d028ad7e296ef87954db2699198e0c3be --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/dune-project @@ -0,0 +1,3 @@ +(lang dune 2.0) +(formatting (enabled_for ocaml)) +(name tezos-alpha-test-helpers) diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/expr.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/expr.ml new file mode 100644 index 0000000000000000000000000000000000000000..9242fb6cb05efedb60f8df8256165082bd48242f --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/expr.ml @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +exception Expression_from_string + +let from_string str : Script.expr = + let (ast, errs) = Michelson_v1_parser.parse_expression ~check:false str in + ( match errs with + | [] -> + () + | lst -> + Format.printf "expr_from_string: %a\n" Error_monad.pp_print_error lst ; + raise Expression_from_string ) ; + ast.expanded diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/incremental.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/incremental.ml new file mode 100644 index 0000000000000000000000000000000000000000..5b3de2a4ff47a7bf2267445fd674a51b4c299469 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/incremental.ml @@ -0,0 +1,215 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = { + predecessor : Block.t; + state : validation_state; + rev_operations : Operation.packed list; + rev_tickets : operation_receipt list; + header : Block_header.t; + delegate : Account.t; +} + +type incremental = t + +let predecessor {predecessor; _} = predecessor + +let header {header; _} = header + +let rev_tickets {rev_tickets; _} = rev_tickets + +let validation_state {state; _} = state + +let level st = st.header.shell.level + +let rpc_context st = + let result = Alpha_context.finalize st.state.ctxt in + { + Environment.Updater.block_hash = Block_hash.zero; + block_header = {st.header.shell with fitness = result.fitness}; + context = result.context; + } + +let rpc_ctxt = + new Environment.proto_rpc_context_of_directory rpc_context rpc_services + +let alpha_ctxt st = st.state.ctxt + +let begin_construction ?(priority = 0) ?timestamp ?seed_nonce_hash + ?(policy = Block.By_priority priority) (predecessor : Block.t) = + Block.get_next_baker ~policy predecessor + >>=? fun (delegate, priority, _timestamp) -> + Alpha_services.Delegate.Minimal_valid_time.get + Block.rpc_ctxt + predecessor + priority + 0 + >>=? fun real_timestamp -> + Account.find delegate + >>=? fun delegate -> + let timestamp = Option.value ~default:real_timestamp timestamp in + let contents = Block.Forge.contents ~priority ?seed_nonce_hash () in + let protocol_data = {Block_header.contents; signature = Signature.zero} in + let header = + { + Block_header.shell = + { + predecessor = predecessor.hash; + proto_level = predecessor.header.shell.proto_level; + validation_passes = predecessor.header.shell.validation_passes; + fitness = predecessor.header.shell.fitness; + timestamp; + level = predecessor.header.shell.level; + context = Context_hash.zero; + operations_hash = Operation_list_list_hash.zero; + }; + protocol_data = {contents; signature = Signature.zero}; + } + in + begin_construction + ~chain_id:Chain_id.zero + ~predecessor_context:predecessor.context + ~predecessor_timestamp:predecessor.header.shell.timestamp + ~predecessor_fitness:predecessor.header.shell.fitness + ~predecessor_level:predecessor.header.shell.level + ~predecessor:predecessor.hash + ~timestamp + ~protocol_data + () + >|= fun state -> + Environment.wrap_tzresult state + >|? fun state -> + {predecessor; state; rev_operations = []; rev_tickets = []; header; delegate} + +let detect_script_failure : + type kind. kind Apply_results.operation_metadata -> _ = + let rec detect_script_failure : + type kind. kind Apply_results.contents_result_list -> _ = + let open Apply_results in + let detect_script_failure_single (type kind) + (Manager_operation_result + {operation_result; internal_operation_results; _} : + kind Kind.manager Apply_results.contents_result) = + let detect_script_failure (type kind) + (result : kind manager_operation_result) = + match result with + | Applied _ -> + Ok () + | Skipped _ -> + assert false + | Backtracked (_, None) -> + (* there must be another error for this to happen *) + Ok () + | Backtracked (_, Some errs) -> + Error (Environment.wrap_tztrace errs) + | Failed (_, errs) -> + Error (Environment.wrap_tztrace errs) + in + List.fold_left + (fun acc (Internal_operation_result (_, r)) -> + acc >>? fun () -> detect_script_failure r) + (detect_script_failure operation_result) + internal_operation_results + in + function + | Single_result (Manager_operation_result _ as res) -> + detect_script_failure_single res + | Single_result _ -> + Ok () + | Cons_result (res, rest) -> + detect_script_failure_single res + >>? fun () -> detect_script_failure rest + in + fun {contents} -> detect_script_failure contents + +let add_operation ?expect_apply_failure ?expect_failure st op = + let open Apply_results in + apply_operation st.state op + >|= Environment.wrap_tzresult + >>= fun result -> + match (expect_apply_failure, result) with + | (Some _, Ok _) -> + failwith "Error expected while adding operation" + | (Some f, Error err) -> + f err >|=? fun () -> st + | (None, result) -> ( + result + >>?= fun result -> + match result with + | (state, (Operation_metadata result as metadata)) -> + detect_script_failure result + |> fun result -> + ( match expect_failure with + | None -> + Lwt.return result + | Some f -> ( + match result with + | Ok _ -> + failwith "Error expected while adding operation" + | Error e -> + f e ) ) + >|=? fun () -> + { + st with + state; + rev_operations = op :: st.rev_operations; + rev_tickets = metadata :: st.rev_tickets; + } + | (state, (No_operation_metadata as metadata)) -> + return + { + st with + state; + rev_operations = op :: st.rev_operations; + rev_tickets = metadata :: st.rev_tickets; + } ) + +let finalize_block st = + finalize_block st.state + >|= fun x -> + Environment.wrap_tzresult x + >|? fun (result, _) -> + let operations = List.rev st.rev_operations in + let operations_hash = + Operation_list_list_hash.compute + [Operation_list_hash.compute (List.map Operation.hash_packed operations)] + in + let header = + { + st.header with + shell = + { + st.header.shell with + level = Int32.succ st.header.shell.level; + operations_hash; + fitness = result.fitness; + }; + } + in + let hash = Block_header.hash header in + {Block.hash; header; operations; context = result.context} diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/incremental.mli b/src/proto_009_PsFLoren/lib_protocol/test/helpers/incremental.mli new file mode 100644 index 0000000000000000000000000000000000000000..6d32852544ba941fe03a0d91961b4075a0990f33 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/incremental.mli @@ -0,0 +1,62 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t + +type incremental = t + +val predecessor : incremental -> Block.t + +val header : incremental -> Block_header.t + +val rev_tickets : incremental -> operation_receipt list + +val validation_state : incremental -> validation_state + +val level : incremental -> int32 + +val begin_construction : + ?priority:int -> + ?timestamp:Time.Protocol.t -> + ?seed_nonce_hash:Nonce_hash.t -> + ?policy:Block.baker_policy -> + Block.t -> + incremental tzresult Lwt.t + +val add_operation : + ?expect_apply_failure:(error list -> unit tzresult Lwt.t) -> + ?expect_failure:(error list -> unit tzresult Lwt.t) -> + incremental -> + Operation.packed -> + incremental tzresult Lwt.t + +val finalize_block : incremental -> Block.t tzresult Lwt.t + +val rpc_ctxt : incremental Environment.RPC_context.simple + +val alpha_ctxt : incremental -> Alpha_context.context diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/nonce.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/nonce.ml new file mode 100644 index 0000000000000000000000000000000000000000..2df42cad01e1c22f904eb3e5bf67d598c273dec6 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/nonce.ml @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* Copyright (c) 2014 - 2018. *) +(* Dynamic Ledger Solutions, Inc.< contact@tezos.com > *) +(* *) +(* All rights reserved.No warranty, explicit or implicit, provided. *) +(* *) +(**************************************************************************) + +open Protocol + +module Table = Hashtbl.Make (struct + type t = Nonce_hash.t + + let hash h = Int32.to_int (TzEndian.get_int32 (Nonce_hash.to_bytes h) 0) + + let equal = Nonce_hash.equal +end) + +let known_nonces = Table.create 17 + +let generate () = + match + Alpha_context.Nonce.of_bytes + @@ Rand.generate Alpha_context.Constants.nonce_length + with + | Ok nonce -> + let hash = Alpha_context.Nonce.hash nonce in + Table.add known_nonces hash nonce ; + (hash, nonce) + | Error _ -> + assert false + +let forget_all () = Table.clear known_nonces + +let get hash = Table.find known_nonces hash diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/nonce.mli b/src/proto_009_PsFLoren/lib_protocol/test/helpers/nonce.mli new file mode 100644 index 0000000000000000000000000000000000000000..8a8b258b065852028e44aad28577dbcb231c6ef3 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/nonce.mli @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** Returns a fresh nonce and its corresponding hash (and stores them). *) +val generate : unit -> Nonce_hash.t * Alpha_context.Nonce.t + +val get : Nonce_hash.t -> Alpha_context.Nonce.t option + +val forget_all : unit -> unit diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/op.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/op.ml new file mode 100644 index 0000000000000000000000000000000000000000..c2af4dc7cd18888f20e49a883a68fb63b6349648 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/op.ml @@ -0,0 +1,430 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let sign ?(watermark = Signature.Generic_operation) sk ctxt contents = + let branch = Context.branch ctxt in + let unsigned = + Data_encoding.Binary.to_bytes_exn + Operation.unsigned_encoding + ({branch}, Contents_list contents) + in + let signature = Some (Signature.sign ~watermark sk unsigned) in + ({shell = {branch}; protocol_data = {contents; signature}} : _ Operation.t) + +let endorsement ?delegate ?level ctxt ?(signing_context = ctxt) () = + ( match delegate with + | None -> + Context.get_endorser ctxt >|=? fun (delegate, _slots) -> delegate + | Some delegate -> + return delegate ) + >>=? fun delegate_pkh -> + Account.find delegate_pkh + >>=? fun delegate -> + Lwt.return + ( ( match level with + | None -> + Context.get_level ctxt + | Some level -> + ok level ) + >|? fun level -> + let op = Single (Endorsement {level}) in + sign + ~watermark:Signature.(Endorsement Chain_id.zero) + delegate.sk + signing_context + op ) + +let endorsement_with_slot ?delegate ?level ctxt ?(signing_context = ctxt) () = + (match delegate with None -> Context.get_endorser ctxt | Some v -> return v) + >>=? fun (delegate_pkh, slots) -> + let slot = WithExceptions.Option.get ~loc:__LOC__ (List.hd slots) in + Account.find delegate_pkh + >>=? fun delegate -> + Lwt.return + ( ( match level with + | None -> + Context.get_level ctxt + | Some level -> + ok level ) + >|? fun level -> + let op = Single (Endorsement {level}) in + let endorsement = + sign + ~watermark:Signature.(Endorsement Chain_id.zero) + delegate.sk + signing_context + op + in + ( { + shell = endorsement.shell; + protocol_data = + { + contents = Single (Endorsement_with_slot {endorsement; slot}); + signature = None; + }; + } + : Kind.endorsement_with_slot Operation.t ) ) + +let sign ?watermark sk ctxt (Contents_list contents) = + Operation.pack (sign ?watermark sk ctxt contents) + +let combine_operations ?public_key ?counter ?spurious_operation ~source ctxt + (packed_operations : packed_operation list) = + assert (List.length packed_operations > 0) ; + (* Hypothesis : each operation must have the same branch (is this really true?) *) + let {Tezos_base.Operation.branch} = + (WithExceptions.Option.get ~loc:__LOC__ @@ List.hd packed_operations).shell + in + assert ( + List.for_all + (fun {shell = {Tezos_base.Operation.branch = b; _}; _} -> + Block_hash.(branch = b)) + packed_operations ) ; + (* TODO? : check signatures consistency *) + let unpacked_operations = + List.map + (function + | {Alpha_context.protocol_data = Operation_data {contents; _}; _} -> ( + match Contents_list contents with + | Contents_list (Single o) -> + Contents o + | Contents_list + (Cons (Manager_operation {operation = Reveal _; _}, Single o)) -> + Contents o + | _ -> + (* TODO : decent error *) assert false )) + packed_operations + in + ( match counter with + | Some counter -> + return counter + | None -> + Context.Contract.counter ctxt source ) + >>=? fun counter -> + (* We increment the counter *) + let counter = Z.succ counter in + Context.Contract.manager ctxt source + >>=? fun account -> + let public_key = Option.value ~default:account.pk public_key in + Context.Contract.is_manager_key_revealed ctxt source + >|=? (function + | false -> + let reveal_op = + Manager_operation + { + source = Signature.Public_key.hash public_key; + fee = Tez.zero; + counter; + operation = Reveal public_key; + gas_limit = Gas.Arith.integral_of_int_exn 10_000; + storage_limit = Z.zero; + } + in + (Some (Contents reveal_op), Z.succ counter) + | true -> + (None, counter)) + >|=? fun (manager_op, counter) -> + (* Update counters and transform into a contents_list *) + let operations = + List.fold_left + (fun (counter, acc) -> function Contents (Manager_operation m) -> + ( Z.succ counter, + Contents (Manager_operation {m with counter}) :: acc ) | x -> + (counter, x :: acc)) + (counter, match manager_op with None -> [] | Some op -> [op]) + unpacked_operations + |> snd |> List.rev + in + (* patch a random operation with a corrupted pkh *) + let operations = + match spurious_operation with + | None -> + operations + | Some op -> ( + let op = + match op with + | {protocol_data; shell = _} -> ( + match protocol_data with + | Operation_data {contents; _} -> ( + match contents with + | Cons _ -> + assert false + | Single op -> + Alpha_context.Contents op ) ) + in + (* Select where to insert spurious op *) + let legit_ops = List.length operations in + let index = Random.int legit_ops in + match List.split_n index operations with + | (preserved_prefix, preserved_suffix) -> + preserved_prefix @ (op :: preserved_suffix) ) + in + let operations = Operation.of_list operations in + sign account.sk ctxt operations + +let manager_operation ?counter ?(fee = Tez.zero) ?gas_limit ?storage_limit + ?public_key ~source ctxt operation = + ( match counter with + | Some counter -> + return counter + | None -> + Context.Contract.counter ctxt source ) + >>=? fun counter -> + Context.get_constants ctxt + >>=? fun c -> + let gas_limit = + let default = c.parametric.hard_gas_limit_per_operation in + Option.value ~default gas_limit + in + let storage_limit = + Option.value + ~default:c.parametric.hard_storage_limit_per_operation + storage_limit + in + Context.Contract.manager ctxt source + >>=? fun account -> + let public_key = Option.value ~default:account.pk public_key in + let counter = Z.succ counter in + Context.Contract.is_manager_key_revealed ctxt source + >|=? function + | true -> + let op = + Manager_operation + { + source = Signature.Public_key.hash public_key; + fee; + counter; + operation; + gas_limit; + storage_limit; + } + in + Contents_list (Single op) + | false -> + let op_reveal = + Manager_operation + { + source = Signature.Public_key.hash public_key; + fee = Tez.zero; + counter; + operation = Reveal public_key; + gas_limit = Gas.Arith.integral_of_int_exn 10000; + storage_limit = Z.zero; + } + in + let op = + Manager_operation + { + source = Signature.Public_key.hash public_key; + fee; + counter = Z.succ counter; + operation; + gas_limit; + storage_limit; + } + in + Contents_list (Cons (op_reveal, Single op)) + +let revelation ?(fee = Tez.zero) ctxt public_key = + let pkh = Signature.Public_key.hash public_key in + let source = Contract.implicit_contract pkh in + Context.Contract.counter ctxt source + >>=? fun counter -> + Context.Contract.manager ctxt source + >|=? fun account -> + let counter = Z.succ counter in + let sop = + Contents_list + (Single + (Manager_operation + { + source = Signature.Public_key.hash public_key; + fee; + counter; + operation = Reveal public_key; + gas_limit = Gas.Arith.integral_of_int_exn 10000; + storage_limit = Z.zero; + })) + in + sign account.sk ctxt sop + +let failing_noop ctxt source arbitrary = + let op = Contents_list (Single (Failing_noop arbitrary)) in + Account.find source >>=? fun account -> return @@ sign account.sk ctxt op + +let originated_contract op = + let nonce = Contract.initial_origination_nonce (Operation.hash_packed op) in + Contract.originated_contract nonce + +exception Impossible + +let origination ?counter ?delegate ~script ?(preorigination = None) ?public_key + ?credit ?fee ?gas_limit ?storage_limit ctxt source = + Context.Contract.manager ctxt source + >>=? fun account -> + let default_credit = Tez.of_mutez @@ Int64.of_int 1000001 in + let default_credit = + WithExceptions.Option.to_exn ~none:Impossible default_credit + in + let credit = Option.value ~default:default_credit credit in + let operation = Origination {delegate; script; credit; preorigination} in + manager_operation + ?counter + ?public_key + ?fee + ?gas_limit + ?storage_limit + ~source + ctxt + operation + >|=? fun sop -> + let op = sign account.sk ctxt sop in + (op, originated_contract op) + +let miss_signed_endorsement ?level ctxt = + (match level with None -> Context.get_level ctxt | Some level -> ok level) + >>?= fun level -> + Context.get_endorser ctxt + >>=? fun (real_delegate_pkh, _slots) -> + let delegate = Account.find_alternate real_delegate_pkh in + endorsement ~delegate:delegate.pkh ~level ctxt () + +let transaction ?counter ?fee ?gas_limit ?storage_limit + ?(parameters = Script.unit_parameter) ?(entrypoint = "default") ctxt + (src : Contract.t) (dst : Contract.t) (amount : Tez.t) = + let top = Transaction {amount; parameters; destination = dst; entrypoint} in + manager_operation + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + top + >>=? fun sop -> + Context.Contract.manager ctxt src + >|=? fun account -> sign account.sk ctxt sop + +let delegation ?fee ctxt source dst = + let top = Delegation dst in + manager_operation ?fee ~source ctxt top + >>=? fun sop -> + Context.Contract.manager ctxt source + >|=? fun account -> sign account.sk ctxt sop + +let activation ctxt (pkh : Signature.Public_key_hash.t) activation_code = + ( match pkh with + | Ed25519 edpkh -> + return edpkh + | _ -> + failwith + "Wrong public key hash : %a - Commitments must be activated with an \ + Ed25519 encrypted public key hash" + Signature.Public_key_hash.pp + pkh ) + >|=? fun id -> + let contents = Single (Activate_account {id; activation_code}) in + let branch = Context.branch ctxt in + { + shell = {branch}; + protocol_data = Operation_data {contents; signature = None}; + } + +let double_endorsement ctxt op1 op2 ~slot = + let contents = Single (Double_endorsement_evidence {op1; op2; slot}) in + let branch = Context.branch ctxt in + { + shell = {branch}; + protocol_data = Operation_data {contents; signature = None}; + } + +let double_baking ctxt bh1 bh2 = + let contents = Single (Double_baking_evidence {bh1; bh2}) in + let branch = Context.branch ctxt in + { + shell = {branch}; + protocol_data = Operation_data {contents; signature = None}; + } + +let seed_nonce_revelation ctxt level nonce = + { + shell = {branch = Context.branch ctxt}; + protocol_data = + Operation_data + { + contents = Single (Seed_nonce_revelation {level; nonce}); + signature = None; + }; + } + +let proposals ctxt (pkh : Contract.t) proposals = + Context.Contract.pkh pkh + >>=? fun source -> + Context.Vote.get_current_period ctxt + >>=? fun {voting_period = {index; _}; _} -> + let op = Proposals {source; period = index; proposals} in + Account.find source + >|=? fun account -> sign account.sk ctxt (Contents_list (Single op)) + +let ballot ctxt (pkh : Contract.t) proposal ballot = + Context.Contract.pkh pkh + >>=? fun source -> + Context.Vote.get_current_period ctxt + >>=? fun {voting_period = {index; _}; _} -> + let op = Ballot {source; period = index; proposal; ballot} in + Account.find source + >|=? fun account -> sign account.sk ctxt (Contents_list (Single op)) + +let dummy_script = + let open Micheline in + Script. + { + code = + lazy_expr + (strip_locations + (Seq + ( 0, + [ Prim (0, K_parameter, [Prim (0, T_unit, [], [])], []); + Prim (0, K_storage, [Prim (0, T_unit, [], [])], []); + Prim + ( 0, + K_code, + [ Seq + ( 0, + [ Prim (0, I_CDR, [], []); + Prim + ( 0, + I_NIL, + [Prim (0, T_operation, [], [])], + [] ); + Prim (0, I_PAIR, [], []) ] ) ], + [] ) ] ))); + storage = lazy_expr (strip_locations (Prim (0, D_Unit, [], []))); + } + +let dummy_script_cost = Test_tez.Tez.of_mutez_exn 9_500L diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/op.mli b/src/proto_009_PsFLoren/lib_protocol/test/helpers/op.mli new file mode 100644 index 0000000000000000000000000000000000000000..6d569d47eb7039c5d980e76c4b3016ff7c690097 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/op.mli @@ -0,0 +1,141 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +val endorsement : + ?delegate:public_key_hash -> + ?level:Raw_level.t -> + Context.t -> + ?signing_context:Context.t -> + unit -> + Kind.endorsement Operation.t tzresult Lwt.t + +val endorsement_with_slot : + ?delegate:public_key_hash * int list -> + ?level:Raw_level.t -> + Context.t -> + ?signing_context:Context.t -> + unit -> + Kind.endorsement_with_slot Operation.t tzresult Lwt.t + +val miss_signed_endorsement : + ?level:Raw_level.t -> + Context.t -> + Kind.endorsement Operation.t tzresult Lwt.t + +val transaction : + ?counter:Z.t -> + ?fee:Tez.tez -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?parameters:Script.lazy_expr -> + ?entrypoint:string -> + Context.t -> + Contract.t -> + Contract.t -> + Tez.t -> + Operation.packed tzresult Lwt.t + +val delegation : + ?fee:Tez.tez -> + Context.t -> + Contract.t -> + public_key_hash option -> + Operation.packed tzresult Lwt.t + +val revelation : + ?fee:Tez.tez -> Context.t -> public_key -> Operation.packed tzresult Lwt.t + +val failing_noop : + Context.t -> public_key_hash -> string -> Operation.packed tzresult Lwt.t + +val origination : + ?counter:Z.t -> + ?delegate:public_key_hash -> + script:Script.t -> + ?preorigination:Contract.contract option -> + ?public_key:public_key -> + ?credit:Tez.tez -> + ?fee:Tez.tez -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + Context.t -> + Contract.contract -> + (Operation.packed * Contract.contract) tzresult Lwt.t + +val originated_contract : Operation.packed -> Contract.contract + +val double_endorsement : + Context.t -> + Kind.endorsement Operation.t -> + Kind.endorsement Operation.t -> + slot:int -> + Operation.packed + +val double_baking : + Context.t -> + Block_header.block_header -> + Block_header.block_header -> + Operation.packed + +val activation : + Context.t -> + Signature.Public_key_hash.t -> + Blinded_public_key_hash.activation_code -> + Operation.packed tzresult Lwt.t + +val combine_operations : + ?public_key:public_key -> + ?counter:counter -> + ?spurious_operation:packed_operation -> + source:Contract.t -> + Context.t -> + packed_operation list -> + packed_operation tzresult Lwt.t + +(** Reveals a seed_nonce that was previously committed at a certain level *) +val seed_nonce_revelation : + Context.t -> Raw_level.t -> Nonce.t -> Operation.packed + +(** Propose a list of protocol hashes during the approval voting *) +val proposals : + Context.t -> + Contract.t -> + Protocol_hash.t list -> + Operation.packed tzresult Lwt.t + +(** Cast a vote yay, nay or pass *) +val ballot : + Context.t -> + Contract.t -> + Protocol_hash.t -> + Vote.ballot -> + Operation.packed tzresult Lwt.t + +val dummy_script : Script.t + +val dummy_script_cost : Test_tez.Tez.t diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/rewards.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/rewards.ml new file mode 100644 index 0000000000000000000000000000000000000000..55fab74541c79fe9b10adf33621a9397fc10be60 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/rewards.ml @@ -0,0 +1,281 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs, *) +(* Copyright (c) 2019 Cryptium Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The tables are precomputed using this the following formulas: + +let max_endos = 32 +let max_reward = 80 + +let r = 0.5 +let a = 6. +let b = 1.5 + +let ( -- ) i j = List.init (j - i + 1) (fun x -> x + i) + +let baking_rewards = + let reward p e = + let r_aux = + if p = 0 then + r *. (float_of_int max_reward) + else + a + in + let r = r_aux *. (float_of_int e) /. (float_of_int max_endos) in + let r = 1_000_000. *. r in + Float.to_int (floor r) in + + let ps = 0 -- 2 in + let es = 0 -- 32 in + + List.map (fun p -> + List.map (fun e -> + reward p e + ) es |> Array.of_list + ) ps |> Array.of_list + + +let endorsing_rewards = + let reward p e = + let r_aux = + (1. -. r) *. + (float_of_int max_reward) /. + (float_of_int max_endos) in + let r = if p = 0 then r_aux else r_aux /. b in + let r = 1_000_000. *. r in + Float.to_int ((float_of_int e) *. (floor r)) in + + let ps = 0 -- 2 in + let es = 0 -- 32 in + + List.map (fun p -> + List.map (fun e -> + reward p e + ) es |> Array.of_list + ) ps |> Array.of_list + + *) + +let baking_rewards : int array array = + [| [| 0; + 1250000; + 2500000; + 3750000; + 5000000; + 6250000; + 7500000; + 8750000; + 10000000; + 11250000; + 12500000; + 13750000; + 15000000; + 16250000; + 17500000; + 18750000; + 20000000; + 21250000; + 22500000; + 23750000; + 25000000; + 26250000; + 27500000; + 28750000; + 30000000; + 31250000; + 32500000; + 33750000; + 35000000; + 36250000; + 37500000; + 38750000; + 40000000 |]; + [| 0; + 187500; + 375000; + 562500; + 750000; + 937500; + 1125000; + 1312500; + 1500000; + 1687500; + 1875000; + 2062500; + 2250000; + 2437500; + 2625000; + 2812500; + 3000000; + 3187500; + 3375000; + 3562500; + 3750000; + 3937500; + 4125000; + 4312500; + 4500000; + 4687500; + 4875000; + 5062500; + 5250000; + 5437500; + 5625000; + 5812500; + 6000000 |]; + [| 0; + 187500; + 375000; + 562500; + 750000; + 937500; + 1125000; + 1312500; + 1500000; + 1687500; + 1875000; + 2062500; + 2250000; + 2437500; + 2625000; + 2812500; + 3000000; + 3187500; + 3375000; + 3562500; + 3750000; + 3937500; + 4125000; + 4312500; + 4500000; + 4687500; + 4875000; + 5062500; + 5250000; + 5437500; + 5625000; + 5812500; + 6000000 |] |] + +let endorsing_rewards : int array array = + [| [| 0; + 1250000; + 2500000; + 3750000; + 5000000; + 6250000; + 7500000; + 8750000; + 10000000; + 11250000; + 12500000; + 13750000; + 15000000; + 16250000; + 17500000; + 18750000; + 20000000; + 21250000; + 22500000; + 23750000; + 25000000; + 26250000; + 27500000; + 28750000; + 30000000; + 31250000; + 32500000; + 33750000; + 35000000; + 36250000; + 37500000; + 38750000; + 40000000 |]; + [| 0; + 833333; + 1666666; + 2499999; + 3333332; + 4166665; + 4999998; + 5833331; + 6666664; + 7499997; + 8333330; + 9166663; + 9999996; + 10833329; + 11666662; + 12499995; + 13333328; + 14166661; + 14999994; + 15833327; + 16666660; + 17499993; + 18333326; + 19166659; + 19999992; + 20833325; + 21666658; + 22499991; + 23333324; + 24166657; + 24999990; + 25833323; + 26666656 |]; + [| 0; + 833333; + 1666666; + 2499999; + 3333332; + 4166665; + 4999998; + 5833331; + 6666664; + 7499997; + 8333330; + 9166663; + 9999996; + 10833329; + 11666662; + 12499995; + 13333328; + 14166661; + 14999994; + 15833327; + 16666660; + 17499993; + 18333326; + 19166659; + 19999992; + 20833325; + 21666658; + 22499991; + 23333324; + 24166657; + 24999990; + 25833323; + 26666656 |] |] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/sapling_helpers.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/sapling_helpers.ml new file mode 100644 index 0000000000000000000000000000000000000000..304c49f77fd1679dffded3ebb7c45fe1d3829b00 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/sapling_helpers.ml @@ -0,0 +1,463 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +module Common = struct + let memo_size_of_int i = + match Alpha_context.Sapling.Memo_size.parse_z @@ Z.of_int i with + | Ok memo_size -> + memo_size + | Error _ -> + assert false + + let int_of_memo_size ms = + Alpha_context.Sapling.Memo_size.unparse_to_z ms |> Z.to_int + + let wrap e = Lwt.return (Environment.wrap_tzresult e) + + let assert_true res = res >|=? fun res -> assert res + + let assert_false res = res >|=? fun res -> assert (not res) + + let assert_some res = res >|=? function Some s -> s | None -> assert false + + let assert_none res = + res >>=? function Some _ -> assert false | None -> return_unit + + let assert_error res = + res >>= function Ok _ -> assert false | Error _ -> return_unit + + let print ?(prefix = "") e v = + Printf.printf + "%s: %s\n" + prefix + Data_encoding.(Json.to_string (Json.construct e v)) + + let to_hex x encoding = + Hex.show (Hex.of_bytes Data_encoding.Binary.(to_bytes_exn encoding x)) + + let randomized_byte ?pos v encoding = + let bytes = Data_encoding.Binary.(to_bytes_exn encoding v) in + let b = Random.bits () in + let random_pos = Random.int (Bytes.length bytes - 1) in + let pos = Option.value ~default:random_pos pos in + Bytes.set_int8 bytes pos b ; + Data_encoding.Binary.(of_bytes_exn encoding bytes) + + type wallet = { + sk : Tezos_sapling.Core.Wallet.Spending_key.t; + vk : Tezos_sapling.Core.Wallet.Viewing_key.t; + } + + let wallet_gen () = + let sk = + Tezos_sapling.Core.Wallet.Spending_key.of_seed + (Tezos_crypto.Hacl.Rand.gen 32) + in + let vk = Tezos_sapling.Core.Wallet.Viewing_key.of_sk sk in + {sk; vk} + + let gen_addr n vk = + let rec aux n index res = + if Compare.Int.( <= ) n 0 then res + else + let (new_index, new_addr) = + Tezos_sapling.Core.Client.Viewing_key.new_address vk index + in + aux (n - 1) new_index (new_addr :: res) + in + aux n Tezos_sapling.Core.Client.Viewing_key.default_index [] + + let gen_nf () = + let {vk; _} = wallet_gen () in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.(new_address vk default_index) + in + let amount = 10L in + let rcm = Tezos_sapling.Core.Client.Rcm.random () in + let position = 10L in + Tezos_sapling.Core.Client.Nullifier.compute addr vk ~amount rcm ~position + + let gen_cm_cipher ~memo_size () = + let open Tezos_sapling.Core.Client in + let {vk; _} = wallet_gen () in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.(new_address vk default_index) + in + let amount = 10L in + let rcm = Tezos_sapling.Core.Client.Rcm.random () in + let cm = Commitment.compute addr ~amount rcm in + let cipher = + let payload_enc = + Data_encoding.Binary.to_bytes_exn + Data_encoding.bytes + (Hacl.Rand.gen (memo_size + 4 + 16 + 11 + 32 + 8)) + in + Data_encoding.Binary.of_bytes_exn + Ciphertext.encoding + (Bytes.concat + Bytes.empty + [ Bytes.create (32 + 32); + payload_enc; + Bytes.create (24 + 64 + 16 + 24) ]) + in + (cm, cipher) + + (* rebuilds from empty at each call *) + let client_state_of_diff ~memo_size (root, diff) = + let open Alpha_context.Sapling in + let cs = + Tezos_sapling.Storage.add + (Tezos_sapling.Storage.empty ~memo_size) + diff.commitments_and_ciphertexts + in + assert (Tezos_sapling.Storage.get_root cs = root) ; + List.fold_left + (fun s nf -> Tezos_sapling.Storage.add_nullifier s nf) + cs + diff.nullifiers +end + +module Alpha_context_helpers = struct + include Common + + let init () = + Context.init 1 + >>=? fun (b, _) -> + Alpha_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >|=? fun (ctxt, _) -> ctxt + + (* takes a state obtained from Sapling.empty_state or Sapling.state_from_id and + passed through Sapling.verify_update *) + let finalize ctx = + let open Alpha_context in + let open Sapling in + function + | {id = None; diff; memo_size} -> + Sapling.fresh ~temporary:false ctx + >>= wrap + >>=? fun (ctx, id) -> + let init = Lazy_storage.Alloc {memo_size} in + let lazy_storage_diff = Lazy_storage.Update {init; updates = diff} in + let diffs = [Lazy_storage.make Sapling_state id lazy_storage_diff] in + Lazy_storage.apply ctx diffs + >>= wrap + >|=? fun (ctx, _added_size) -> (ctx, id) + | {id = Some id; diff; _} -> + let init = Lazy_storage.Existing in + let lazy_storage_diff = Lazy_storage.Update {init; updates = diff} in + let diffs = [Lazy_storage.make Sapling_state id lazy_storage_diff] in + Lazy_storage.apply ctx diffs + >>= wrap + >|=? fun (ctx, _added_size) -> (ctx, id) + + (* disk only version *) + let verify_update ctx ?memo_size ?id vt = + let anti_replay = "anti-replay" in + ( match id with + | None -> + ( match memo_size with + | None -> ( + match vt.Environment.Sapling.UTXO.outputs with + | [] -> + failwith "Can't infer memo_size from empty outputs" + | output :: _ -> + return + @@ Environment.Sapling.Ciphertext.get_memo_size output.ciphertext + ) + | Some memo_size -> + return memo_size ) + >>=? fun memo_size -> + let memo_size = memo_size_of_int memo_size in + let vs = Alpha_context.Sapling.empty_state ~memo_size () in + return (vs, ctx) + | Some id -> + (* Storage.Sapling.Roots.get (Obj.magic ctx, id) 0l *) + (* >>= wrap *) + (* >>=? fun (_, root) -> *) + (* print ~prefix:"verify: " Environment.Sapling.Hash.encoding root ; *) + Alpha_context.Sapling.state_from_id ctx id >>= wrap ) + >>=? fun (vs, ctx) -> + Alpha_context.Sapling.verify_update ctx vs vt anti_replay + >>= wrap + >>=? fun (ctx, res) -> + match res with + | None -> + return_none + | Some (_balance, vs) -> + finalize ctx vs + >>=? fun (ctx, id) -> + let ectx = (Alpha_context.finalize ctx).context in + (* bump the level *) + Alpha_context.prepare + ectx + ~level: + Alpha_context.( + Raw_level.to_int32 Level.((succ ctx (current ctx)).level)) + ~predecessor_timestamp:(Time.Protocol.of_seconds Int64.zero) + ~timestamp:(Time.Protocol.of_seconds Int64.zero) + ~fitness:(Fitness_repr.from_int64 Int64.zero) + >>= wrap + >|=? fun (ctx, _) -> Some (ctx, id) + + let transfer_inputs_outputs w cs is = + (* Tezos_sapling.Storage.size cs *) + (* |> fun (a, b) -> *) + (* Printf.printf "%Ld %Ld" a b ; *) + let inputs = + List.map + (fun i -> + Tezos_sapling.Forge.Input.get cs (Int64.of_int i) w.vk + |> WithExceptions.Option.get ~loc:__LOC__ + |> snd) + is + in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.(new_address w.vk default_index) + in + let memo_size = Tezos_sapling.Storage.get_memo_size cs in + let o = + Tezos_sapling.Forge.make_output addr 1000000L (Bytes.create memo_size) + in + (inputs, [o]) + + let transfer w cs is = + let anti_replay = "anti-replay" in + let (ins, outs) = transfer_inputs_outputs w cs is in + (* change the wallet of this last line *) + Tezos_sapling.Forge.forge_transaction ins outs w.sk anti_replay cs + + let client_state_alpha ctx id = + Alpha_context.Sapling.get_diff ctx id () + >>= wrap + >>=? fun diff -> + Alpha_context.Sapling.state_from_id ctx id + >>= wrap + >|=? fun ({memo_size; _}, _ctx) -> + let memo_size = int_of_memo_size memo_size in + client_state_of_diff ~memo_size diff +end + +(* + Interpreter level +*) + +module Interpreter_helpers = struct + include Common + + (* Initialize 2 addresses to do only operations plus one that will be + used to bake. *) + let init () = + Context.init 3 + >|=? fun (b, contracts) -> + let (src0, src1, src2) = + match contracts with + | src0 :: src1 :: src2 :: _ -> + (src0, src1, src2) + | _ -> + assert false + in + let baker = + match Alpha_context.Contract.is_implicit src0 with + | Some v -> + v + | None -> + assert false + in + (b, baker, src1, src2) + + (* Parse a Michelson contract from string. *) + let toplevel_from_string str = + let (ast, errs) = Michelson_v1_parser.parse_toplevel ~check:true str in + match errs with + | [] -> + ast.expanded + | _ -> + Stdlib.failwith "parse toplevel" + + (* Parse a Michelson expression from string, useful for call parameters. *) + let expression_from_string str = + let (ast, errs) = Michelson_v1_parser.parse_expression ~check:true str in + match errs with + | [] -> + ast.expanded + | _ -> + Stdlib.failwith "parse expression" + + (* returns a block in which the contract is originated. + Also returns the associtaed anti-replay string and KT1 address. *) + let originate_contract file storage src b baker = + let load_file f = + let ic = open_in f in + let res = really_input_string ic (in_channel_length ic) in + close_in ic ; res + in + let contract_string = load_file file in + let code = toplevel_from_string contract_string in + let storage = expression_from_string storage in + let script = + Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} + in + Op.origination (B b) src ~fee:(Test_tez.Tez.of_int 10) ~script + >>=? fun (operation, dst) -> + Incremental.begin_construction ~policy:Block.(By_account baker) b + >>=? fun incr -> + Incremental.add_operation incr operation + >>=? fun incr -> + Incremental.finalize_block incr + >|=? fun b -> + let anti_replay = + Format.asprintf + "%a%a" + Alpha_context.Contract.pp + dst + Chain_id.pp + Chain_id.zero + in + (dst, b, anti_replay) + + let hex_shield ~memo_size wallet anti_replay = + let ps = Tezos_sapling.Storage.empty ~memo_size in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.( + new_address wallet.vk default_index) + in + let output = + Tezos_sapling.Forge.make_output addr 15L (Bytes.create memo_size) + in + let pt = + Tezos_sapling.Forge.forge_transaction + [] + [output] + wallet.sk + anti_replay + ps + in + let hex_string = + "0x" + ^ Hex.show + (Hex.of_bytes + Data_encoding.Binary.( + to_bytes_exn + Tezos_sapling.Core.Client.UTXO.transaction_encoding + pt)) + in + hex_string + + (* Make a transaction and sync a local client state. [to_exclude] is the list + of addresses that cannot bake the block*) + let transac_and_sync ~memo_size block parameters amount src dst baker = + Test_tez.Tez.(one_mutez *? Int64.of_int amount) + >>?= fun amount_tez -> + let fee = Test_tez.Tez.of_int 10 in + Op.transaction ~fee (B block) src dst amount_tez ~parameters + >>=? fun operation -> + Incremental.begin_construction ~policy:Block.(By_account baker) block + >>=? fun incr -> + Incremental.add_operation incr operation + >>=? fun incr -> + Incremental.finalize_block incr + >>=? fun block -> + Alpha_services.Contract.single_sapling_get_diff + Block.rpc_ctxt + block + dst + ~offset_commitment:0L + ~offset_nullifier:0L + () + >>=? fun diff -> + let state = client_state_of_diff ~memo_size diff in + Incremental.begin_construction ~policy:Block.(By_account baker) block + >|=? fun incr -> + let ctx = Incremental.alpha_ctxt incr in + (block, ctx, state) + + (* Returns a list of printed shield transactions and their total amount. *) + let shield ~memo_size sk number_transac vk printer anti_replay = + let state = Tezos_sapling.Storage.empty ~memo_size in + let rec aux number_transac number_outputs index amount_output total res = + if Compare.Int.(number_transac <= 0) then (res, total) + else + let (new_index, new_addr) = + Tezos_sapling.Core.Wallet.Viewing_key.(new_address vk index) + in + let outputs = + List.init ~when_negative_length:() number_outputs (fun _ -> + Tezos_sapling.Forge.make_output + new_addr + amount_output + (Bytes.create memo_size)) + |> function + | Error () -> + assert false (* conditional above guards against this *) + | Ok outputs -> + outputs + in + let tr_hex = + to_hex + (Tezos_sapling.Forge.forge_transaction + ~number_dummy_inputs:0 + ~number_dummy_outputs:0 + [] + outputs + sk + anti_replay + state) + Tezos_sapling.Core.Client.UTXO.transaction_encoding + in + aux + (number_transac - 1) + (number_outputs + 1) + new_index + (Int64.add 20L amount_output) + (total + (number_outputs * Int64.to_int amount_output)) + (printer tr_hex :: res) + in + aux + number_transac + 2 + Tezos_sapling.Core.Wallet.Viewing_key.default_index + 20L + 0 + [] + + (* This fails if the operation is not correct wrt the block *) + let next_block block operation = + Incremental.begin_construction block + >>=? fun incr -> + Incremental.add_operation incr operation + >>=? fun incr -> Incremental.finalize_block incr +end diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/test_tez.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/test_tez.ml new file mode 100644 index 0000000000000000000000000000000000000000..e4b75ca9b1e82d4cff4e3d125c73ef01b8383dd1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/test_tez.ml @@ -0,0 +1,65 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Environment + +(* This module is mostly to wrap the errors from the protocol *) +module Tez = struct + include Tez + + let ( +? ) t1 t2 = t1 +? t2 |> wrap_tzresult + + let ( -? ) t1 t2 = t1 -? t2 |> wrap_tzresult + + let ( *? ) t1 t2 = t1 *? t2 |> wrap_tzresult + + let ( /? ) t1 t2 = t1 /? t2 |> wrap_tzresult + + let ( + ) t1 t2 = + match t1 +? t2 with + | Ok r -> + r + | Error _ -> + Pervasives.failwith "adding tez" + + let of_int x = + match Tez.of_mutez (Int64.mul (Int64.of_int x) 1_000_000L) with + | None -> + invalid_arg "tez_of_int" + | Some x -> + x + + let of_mutez_exn x = + match Tez.of_mutez x with + | None -> + invalid_arg "tez_of_mutez" + | Some x -> + x + + let max_tez = + match Tez.of_mutez Int64.max_int with None -> assert false | Some p -> p +end diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/testable.ml b/src/proto_009_PsFLoren/lib_protocol/test/helpers/testable.ml new file mode 100644 index 0000000000000000000000000000000000000000..79cc1d89ff8a444a5b060913c39ee6039e2419ed --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/testable.ml @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let contract : Protocol.Alpha_context.Contract.t Alcotest.testable = + let open Protocol in + let open Alpha_context in + Alcotest.testable Contract.pp Contract.( = ) + +let script_expr : Protocol.Alpha_context.Script.expr Alcotest.testable = + Alcotest.testable Michelson_v1_printer.print_expr ( = ) + +let trace : tztrace Alcotest.testable = Alcotest.testable pp_print_error ( = ) + +let protocol_error : Environment.Error_monad.error Alcotest.testable = + let open Environment.Error_monad in + Alcotest.testable pp ( = ) diff --git a/src/proto_009_PsFLoren/lib_protocol/test/helpers/tezos-009-PsFLoren-test-helpers.opam b/src/proto_009_PsFLoren/lib_protocol/test/helpers/tezos-009-PsFLoren-test-helpers.opam new file mode 100644 index 0000000000000000000000000000000000000000..2d186c770b7902e1de4bca192ba2672e81bfb896 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/helpers/tezos-009-PsFLoren-test-helpers.opam @@ -0,0 +1,23 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "2.0" } + "tezos-base" + "tezos-stdlib-unix" + "tezos-shell-services" + "tezos-protocol-environment" + "tezos-protocol-009-PsFLoren" + "tezos-protocol-009-PsFLoren-parameters" + "tezos-client-009-PsFLoren" + "alcotest-lwt" +] +build: [ + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol testing framework" diff --git a/src/proto_009_PsFLoren/lib_protocol/test/main.ml b/src/proto_009_PsFLoren/lib_protocol/test/main.ml new file mode 100644 index 0000000000000000000000000000000000000000..e1009de21ed7ecde9b3c2d7b943485695baa6f61 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/main.ml @@ -0,0 +1,63 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol + Invocation: dune build @src/proto_alpha/lib_protocol/runtest + Subject: Entrypoint +*) + +let () = + Alcotest_lwt.run + "protocol_009_PsFLoren" + [ ("transfer", Test_transfer.tests); + ("origination", Test_origination.tests); + ("activation", Test_activation.tests); + ("revelation", Test_reveal.tests); + ("endorsement", Test_endorsement.tests); + ("double endorsement", Test_double_endorsement.tests); + ("double baking", Test_double_baking.tests); + ("seed", Test_seed.tests); + ("baking", Test_baking.tests); + ("delegation", Test_delegation.tests); + ("rolls", Test_rolls.tests); + ("combined", Test_combined_operations.tests); + ("qty", Test_qty.tests); + ("voting", Test_voting.tests); + ("interpretation", Test_interpretation.tests); + ("typechecking", Test_typechecking.tests); + ("gas properties", Test_gas_properties.tests); + ("fixed point computation", Test_fixed_point.tests); + ("gas levels", Test_gas_levels.tests); + ("saturation arithmetic", Test_saturation.tests); + ("gas cost functions", Test_gas_costs.tests); + ("lazy storage diff", Test_lazy_storage_diff.tests); + ("sapling", Test_sapling.tests); + ("helpers rpcs", Test_helpers_rpcs.tests); + ("script deserialize gas", Test_script_gas.tests); + ("failing_noop operation", Test_failing_noop.tests); + ("storage description", Test_storage.tests) ] + |> Lwt_main.run diff --git a/src/proto_009_PsFLoren/lib_protocol/test/saturation_fuzzing.ml b/src/proto_009_PsFLoren/lib_protocol/test/saturation_fuzzing.ml new file mode 100644 index 0000000000000000000000000000000000000000..1447e5ebfb2eee640c00abd19497909097eaac37 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/saturation_fuzzing.ml @@ -0,0 +1,92 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune build @src/proto_alpha/lib_protocol/runtest_saturation_fuzzing + Subject: Operations in Saturation_repr +*) + +open Protocol.Saturation_repr + +let gen_unsaturated = + let open Crowbar in + map [int] safe_int + +let gen_t = + let open Crowbar in + choose + [ const saturated; + gen_unsaturated; + gen_unsaturated; + gen_unsaturated; + gen_unsaturated ] + +(* Test. + * Tests that [f] commutes. + *) +let test_commutes f t1 t2 = + let fapp = f t1 t2 in + let fapp' = f t2 t1 in + Crowbar.check_eq ~pp fapp fapp' + +(* Test. + * Tests that [e] is neutral for [f]. + *) +let test_neutral f e t = + let fapp = f e t in + let fapp' = f t e in + Crowbar.check_eq ~pp fapp fapp' + +(* Test. + * Tests that [t] times [1] equals [t]. + *) +let test_mul_one t = Crowbar.check_eq ~pp (mul t @@ safe_int 1) t + +(* Test. + * Tests that [t] times [0] equals [0]. + *) +let test_mul_zero t = Crowbar.check_eq ~pp (mul t zero) (zero |> may_saturate) + +(* Test. + * Tests that [t] minus [zero] equals [t]. + *) +let test_sub_zero t = Crowbar.check_eq ~pp (sub t zero) t + +let tests = + Crowbar.add_test ~name:"add commutes" [gen_t; gen_t] (test_commutes add) ; + Crowbar.add_test ~name:"mul commutes" [gen_t; gen_t] (test_commutes mul) ; + Crowbar.add_test + ~name:"0 is neutral for add" + [gen_t] + (test_neutral add (zero |> may_saturate)) ; + Crowbar.add_test + ~name:"1 is neutral for mul" + [gen_t] + (test_neutral mul (safe_int 1)) ; + Crowbar.add_test ~name:"t * 0 = 0" [gen_t] test_mul_zero ; + Crowbar.add_test ~name:"t * 1 = t" [gen_t] test_mul_one ; + Crowbar.add_test ~name:"t - 0 = t" [gen_t] test_sub_zero diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_activation.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_activation.ml new file mode 100644 index 0000000000000000000000000000000000000000..989f0dd95ed74d817940e490ff4aba455ebc3445 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_activation.ml @@ -0,0 +1,616 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (activation) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^activation$" + Subject: The activation operation creates an implicit contract from a + registered commitment present in the context. It is + parametrized by a public key hash (pkh) and a secret. + + The commitments are composed of : + - a blinded pkh that can be revealed by the secret ; + - an amount. + + The commitments and the secrets are generated from + /scripts/create_genesis/create_genesis.py and should be + coherent. +*) + +open Protocol +open Alpha_context +open Test_tez + +(* Generated commitments and secrets *) + +(* Commitments are hard-coded in {Tezos_proto_alpha_parameters.Default_parameters} *) + +(* let commitments = + * List.map (fun (bpkh, a) -> + * Commitment_repr.{ + * blinded_public_key_hash=Blinded_public_key_hash.of_b58check_exn bpkh ; + * amount = Tez_repr.of_mutez_exn (Int64.of_string a)} + * ) + * [ ( "btz1bRL4X5BWo2Fj4EsBdUwexXqgTf75uf1qa", "23932454669343" ) ; + * ( "btz1SxjV1syBgftgKy721czKi3arVkVwYUFSv", "72954577464032" ) ; + * ( "btz1LtoNCjiW23txBTenALaf5H6NKF1L3c1gw", "217487035428349" ) ; + * ( "btz1SUd3mMhEBcWudrn8u361MVAec4WYCcFoy", "4092742372031" ) ; + * ( "btz1MvBXf4orko1tsGmzkjLbpYSgnwUjEe81r", "17590039016550" ) ; + * ( "btz1LoDZ3zsjgG3k3cqTpUMc9bsXbchu9qMXT", "26322312350555" ) ; + * ( "btz1RMfq456hFV5AeDiZcQuZhoMv2dMpb9hpP", "244951387881443" ) ; + * ( "btz1Y9roTh4A7PsMBkp8AgdVFrqUDNaBE59y1", "80065050465525" ) ; + * ( "btz1Q1N2ePwhVw5ED3aaRVek6EBzYs1GDkSVD", "3569618927693" ) ; + * ( "btz1VFFVsVMYHd5WfaDTAt92BeQYGK8Ri4eLy", "9034781424478" ) ; + * ] *) + +type secret_account = { + account : public_key_hash; + activation_code : Blinded_public_key_hash.activation_code; + amount : Tez.t; +} + +let secrets () = + (* Exported from proto_alpha client - TODO : remove when relocated to lib_crypto *) + let read_key mnemonic email password = + match Tezos_client_base.Bip39.of_words mnemonic with + | None -> + assert false + | Some t -> + (* TODO: unicode normalization (NFKD)... *) + let passphrase = Bytes.(cat (of_string email) (of_string password)) in + let sk = Tezos_client_base.Bip39.to_seed ~passphrase t in + let sk = Bytes.sub sk 0 32 in + let sk : Signature.Secret_key.t = + Ed25519 + (Data_encoding.Binary.of_bytes_exn Ed25519.Secret_key.encoding sk) + in + let pk = Signature.Secret_key.to_public_key sk in + let pkh = Signature.Public_key.hash pk in + (pkh, pk, sk) + in + List.map + (fun (mnemonic, secret, amount, pkh, password, email) -> + let (pkh', pk, sk) = read_key mnemonic email password in + let pkh = Signature.Public_key_hash.of_b58check_exn pkh in + assert (Signature.Public_key_hash.equal pkh pkh') ; + let account = Account.{pkh; pk; sk} in + Account.add_account account ; + { + account = account.pkh; + activation_code = Blinded_public_key_hash.activation_code_of_hex secret; + amount = + WithExceptions.Option.to_exn + ~none:(Invalid_argument "tez conversion") + (Tez.of_mutez (Int64.of_string amount)); + }) + [ ( [ "envelope"; + "hospital"; + "mind"; + "sunset"; + "cancel"; + "muscle"; + "leisure"; + "thumb"; + "wine"; + "market"; + "exit"; + "lucky"; + "style"; + "picnic"; + "success" ], + "0f39ed0b656509c2ecec4771712d9cddefe2afac", + "23932454669343", + "tz1MawerETND6bqJqx8GV3YHUrvMBCDasRBF", + "z0eZHQQGKt", + "cjgfoqmk.wpxnvnup@tezos.example.org" ); + ( [ "flag"; + "quote"; + "will"; + "valley"; + "mouse"; + "chat"; + "hold"; + "prosper"; + "silk"; + "tent"; + "cruel"; + "cause"; + "demise"; + "bottom"; + "practice" ], + "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4", + "72954577464032", + "tz1X4maqF9tC1Yn4jULjHRAyzjAtc25Z68TX", + "MHErskWPE6", + "oklmcktr.ztljnpzc@tezos.example.org" ); + ( [ "library"; + "away"; + "inside"; + "paper"; + "wise"; + "focus"; + "sweet"; + "expose"; + "require"; + "change"; + "stove"; + "planet"; + "zone"; + "reflect"; + "finger" ], + "411dfef031eeecc506de71c9df9f8e44297cf5ba", + "217487035428348", + "tz1SWBY7rWMutEuWS54Pt33MkzAS6eWkUuTc", + "0AO6BzQNfN", + "ctgnkvqm.kvtiybky@tezos.example.org" ); + ( [ "cruel"; + "fluid"; + "damage"; + "demand"; + "mimic"; + "above"; + "village"; + "alpha"; + "vendor"; + "staff"; + "absent"; + "uniform"; + "fire"; + "asthma"; + "milk" ], + "08d7d355bc3391d12d140780b39717d9f46fcf87", + "4092742372031", + "tz1amUjiZaevaxQy5wKn4SSRvVoERCip3nZS", + "9kbZ7fR6im", + "bnyxxzqr.tdszcvqb@tezos.example.org" ); + ( [ "opera"; + "divorce"; + "easy"; + "myself"; + "idea"; + "aim"; + "dash"; + "scout"; + "case"; + "resource"; + "vote"; + "humor"; + "ticket"; + "client"; + "edge" ], + "9b7cad042fba557618bdc4b62837c5f125b50e56", + "17590039016550", + "tz1Zaee3QBtD4ErY1SzqUvyYTrENrExu6yQM", + "suxT5H09yY", + "iilkhohu.otnyuvna@tezos.example.org" ); + ( [ "token"; + "similar"; + "ginger"; + "tongue"; + "gun"; + "sort"; + "piano"; + "month"; + "hotel"; + "vote"; + "undo"; + "success"; + "hobby"; + "shell"; + "cart" ], + "124c0ca217f11ffc6c7b76a743d867c8932e5afd", + "26322312350555", + "tz1geDUUhfXK1EMj7VQdRjug1MoFe6gHWnCU", + "4odVdLykaa", + "kwhlglvr.slriitzy@tezos.example.org" ); + ( [ "shield"; + "warrior"; + "gorilla"; + "birth"; + "steak"; + "neither"; + "feel"; + "only"; + "liberty"; + "float"; + "oven"; + "extend"; + "pulse"; + "suffer"; + "vapor" ], + "ac7a2125beea68caf5266a647f24dce9fea018a7", + "244951387881443", + "tz1h3nY7jcZciJgAwRhWcrEwqfVp7VQoffur", + "A6yeMqBFG8", + "lvrmlbyj.yczltcxn@tezos.example.org" ); + ( [ "waste"; + "open"; + "scan"; + "tip"; + "subway"; + "dance"; + "rent"; + "copper"; + "garlic"; + "laundry"; + "defense"; + "clerk"; + "another"; + "staff"; + "liar" ], + "2b3e94be133a960fa0ef87f6c0922c19f9d87ca2", + "80065050465525", + "tz1VzL4Xrb3fL3ckvqCWy6bdGMzU2w9eoRqs", + "oVZqpq60sk", + "rfodmrha.zzdndvyk@tezos.example.org" ); + ( [ "fiber"; + "next"; + "property"; + "cradle"; + "silk"; + "obey"; + "gossip"; + "push"; + "key"; + "second"; + "across"; + "minimum"; + "nice"; + "boil"; + "age" ], + "dac31640199f2babc157aadc0021cd71128ca9ea", + "3569618927693", + "tz1RUHg536oRKhPLFfttcB5gSWAhh4E9TWjX", + "FfytQTTVbu", + "owecikdy.gxnyttya@tezos.example.org" ); + ( [ "print"; + "labor"; + "budget"; + "speak"; + "poem"; + "diet"; + "chunk"; + "eternal"; + "book"; + "saddle"; + "pioneer"; + "ankle"; + "happy"; + "only"; + "exclude" ], + "bb841227f250a066eb8429e56937ad504d7b34dd", + "9034781424478", + "tz1M1LFbgctcPWxstrao9aLr2ECW1fV4pH5u", + "zknAl3lrX2", + "ettilrvh.zsrqrbud@tezos.example.org" ) ] + +(** Helper: Create a genesis block with predefined commitments, + accounts and balances. *) +let activation_init () = + Context.init ~with_commitments:true 1 + >|=? fun (b, cs) -> secrets () |> fun ss -> (b, cs, ss) + +(** Verify the genesis block created by [activation_init] can be + baked. *) +let test_simple_init_with_commitments () = + activation_init () + >>=? fun (blk, _contracts, _secrets) -> + Block.bake blk >>=? fun _ -> return_unit + +(** A single activation *) +let test_single_activation () = + activation_init () + >>=? fun (blk, _contracts, secrets) -> + let ({account; activation_code; amount = expected_amount; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + (* Contract does not exist *) + Assert.balance_is + ~loc:__LOC__ + (B blk) + (Contract.implicit_contract account) + Tez.zero + >>=? fun () -> + Op.activation (B blk) account activation_code + >>=? fun operation -> + Block.bake ~operation blk + >>=? fun blk -> + (* Contract does exist *) + Assert.balance_is + ~loc:__LOC__ + (B blk) + (Contract.implicit_contract account) + expected_amount + +(** 10 activations, one per bake. *) +let test_multi_activation_1 () = + activation_init () + >>=? fun (blk, _contracts, secrets) -> + List.fold_left_es + (fun blk {account; activation_code; amount = expected_amount; _} -> + Op.activation (B blk) account activation_code + >>=? fun operation -> + Block.bake ~operation blk + >>=? fun blk -> + Assert.balance_is + ~loc:__LOC__ + (B blk) + (Contract.implicit_contract account) + expected_amount + >|=? fun () -> blk) + blk + secrets + >>=? fun _ -> return_unit + +(** All of the 10 activations occur in one bake. *) +let test_multi_activation_2 () = + activation_init () + >>=? fun (blk, _contracts, secrets) -> + List.fold_left_es + (fun ops {account; activation_code; _} -> + Op.activation (B blk) account activation_code >|=? fun op -> op :: ops) + [] + secrets + >>=? fun ops -> + Block.bake ~operations:ops blk + >>=? fun blk -> + List.iter_es + (fun {account; amount = expected_amount; _} -> + (* Contract does exist *) + Assert.balance_is + ~loc:__LOC__ + (B blk) + (Contract.implicit_contract account) + expected_amount) + secrets + +(** Transfer with activated account. *) +let test_activation_and_transfer () = + activation_init () + >>=? fun (blk, contracts, secrets) -> + let ({account; activation_code; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let bootstrap_contract = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts + in + let first_contract = Contract.implicit_contract account in + Op.activation (B blk) account activation_code + >>=? fun operation -> + Block.bake ~operation blk + >>=? fun blk -> + Context.Contract.balance (B blk) bootstrap_contract + >>=? fun amount -> + Tez.( /? ) amount 2L + >>?= fun half_amount -> + Context.Contract.balance (B blk) first_contract + >>=? fun activated_amount_before -> + Op.transaction (B blk) bootstrap_contract first_contract half_amount + >>=? fun operation -> + Block.bake ~operation blk + >>=? fun blk -> + Assert.balance_was_credited + ~loc:__LOC__ + (B blk) + (Contract.implicit_contract account) + activated_amount_before + half_amount + +(** Transfer to an unactivated account and then activating it. *) +let test_transfer_to_unactivated_then_activate () = + activation_init () + >>=? fun (blk, contracts, secrets) -> + let ({account; activation_code; amount} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let bootstrap_contract = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts + in + let unactivated_commitment_contract = Contract.implicit_contract account in + Context.Contract.balance (B blk) bootstrap_contract + >>=? fun b_amount -> + Tez.( /? ) b_amount 2L + >>?= fun b_half_amount -> + Incremental.begin_construction blk + >>=? fun inc -> + Op.transaction + (I inc) + bootstrap_contract + unactivated_commitment_contract + b_half_amount + >>=? fun op -> + Incremental.add_operation inc op + >>=? fun inc -> + Op.activation (I inc) account activation_code + >>=? fun op' -> + Incremental.add_operation inc op' + >>=? fun inc -> + Incremental.finalize_block inc + >>=? fun blk2 -> + Assert.balance_was_credited + ~loc:__LOC__ + (B blk2) + (Contract.implicit_contract account) + amount + b_half_amount + +(****************************************************************) +(* The following test scenarios are supposed to raise errors. *) +(****************************************************************) + +(** Invalid pkh activation: expected to fail as the context does not + contain any commitment. *) +let test_invalid_activation_with_no_commitments () = + Context.init 1 + >>=? fun (blk, _) -> + let secrets = secrets () in + let ({account; activation_code; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + Op.activation (B blk) account activation_code + >>=? fun operation -> + Block.bake ~operation blk + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Invalid_activation _ -> + true + | _ -> + false) + +(** Wrong activation: wrong secret given in the operation. *) +let test_invalid_activation_wrong_secret () = + activation_init () + >>=? fun (blk, _, secrets) -> + let ({account; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth secrets 0 + in + let ({activation_code; _} as _second_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth secrets 1 + in + Op.activation (B blk) account activation_code + >>=? fun operation -> + Block.bake ~operation blk + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Invalid_activation _ -> + true + | _ -> + false) + +(** Invalid pkh activation : expected to fail as the context does not + contain an associated commitment. *) +let test_invalid_activation_inexistent_pkh () = + activation_init () + >>=? fun (blk, _, secrets) -> + let ({activation_code; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let inexistent_pkh = + Signature.Public_key_hash.of_b58check_exn + "tz1PeQHGKPWSpNoozvxgqLN9TFsj6rDqNV3o" + in + Op.activation (B blk) inexistent_pkh activation_code + >>=? fun operation -> + Block.bake ~operation blk + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Invalid_activation _ -> + true + | _ -> + false) + +(** Invalid pkh activation : expected to fail as the commitment has + already been claimed. *) +let test_invalid_double_activation () = + activation_init () + >>=? fun (blk, _, secrets) -> + let ({account; activation_code; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + Incremental.begin_construction blk + >>=? fun inc -> + Op.activation (I inc) account activation_code + >>=? fun op -> + Incremental.add_operation inc op + >>=? fun inc -> + Op.activation (I inc) account activation_code + >>=? fun op' -> + Incremental.add_operation inc op' + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Invalid_activation _ -> + true + | _ -> + false) + +(** Transfer from an unactivated commitment account. *) +let test_invalid_transfer_from_unactivated_account () = + activation_init () + >>=? fun (blk, contracts, secrets) -> + let ({account; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let bootstrap_contract = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts + in + let unactivated_commitment_contract = Contract.implicit_contract account in + (* No activation *) + Op.transaction + (B blk) + unactivated_commitment_contract + bootstrap_contract + Tez.one + >>=? fun operation -> + Block.bake ~operation blk + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Contract_storage.Empty_implicit_contract pkh -> + if pkh = account then true else false + | _ -> + false) + +let tests = + [ Test_services.tztest + "init with commitments" + `Quick + test_simple_init_with_commitments; + Test_services.tztest "single activation" `Quick test_single_activation; + Test_services.tztest + "multi-activation one-by-one" + `Quick + test_multi_activation_1; + Test_services.tztest + "multi-activation all at a time" + `Quick + test_multi_activation_2; + Test_services.tztest + "activation and transfer" + `Quick + test_activation_and_transfer; + Test_services.tztest + "transfer to unactivated account then activate" + `Quick + test_transfer_to_unactivated_then_activate; + Test_services.tztest + "invalid activation with no commitments" + `Quick + test_invalid_activation_with_no_commitments; + Test_services.tztest + "invalid activation with commitments" + `Quick + test_invalid_activation_inexistent_pkh; + Test_services.tztest + "invalid double activation" + `Quick + test_invalid_double_activation; + Test_services.tztest + "wrong activation code" + `Quick + test_invalid_activation_wrong_secret; + Test_services.tztest + "invalid transfer from unactivated account" + `Quick + test_invalid_transfer_from_unactivated_account ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_baking.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_baking.ml new file mode 100644 index 0000000000000000000000000000000000000000..5daa9183db5144f05c6edb1ecac28a3d8470e4b4 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_baking.ml @@ -0,0 +1,310 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (baking) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^baking$" + Subject: Rewards and bakers. Tests based on RPCs. +*) + +open Protocol +open Alpha_context + +(** Verify the level is correctly computed when the first cycle is + passed and after baking a certain fixed number of blocks (10 for + the moment). The result should be [blocks_per_cycle + 10] where + [blocks_per_cycle] comes from the constants of the selected + protocol. + + IMPROVEMENTS: + - Randomize the number of cycle. + - Randomize the number of accounts created at the beginning + - Randomize the blocks per cycle. + - Randomize the number of blocks baked after the n cycles baked + previously. *) +let test_cycle () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_constants (B b) + >>=? fun csts -> + let blocks_per_cycle = csts.parametric.blocks_per_cycle in + let pp fmt x = Format.fprintf fmt "%ld" x in + Block.bake b + >>=? fun b -> + Block.bake_until_cycle_end b + >>=? fun b -> + Context.get_level (B b) + >>?= fun curr_level -> + Assert.equal + ~loc:__LOC__ + Int32.equal + "not the right level" + pp + (Alpha_context.Raw_level.to_int32 curr_level) + blocks_per_cycle + >>=? fun () -> + Context.get_level (B b) + >>?= fun l -> + Block.bake_n 10 b + >>=? fun b -> + Context.get_level (B b) + >>?= fun curr_level -> + Assert.equal + ~loc:__LOC__ + Int32.equal + "not the right level" + pp + (Alpha_context.Raw_level.to_int32 curr_level) + (Int32.add (Alpha_context.Raw_level.to_int32 l) 10l) + +(** After baking and/or endorsing a block, the baker and the endorsers + get their reward. *) +let test_rewards_retrieval () = + Context.init 256 + >>=? fun (b, _) -> + Context.get_constants (B b) + >>=? fun Constants. + { parametric = + { endorsers_per_block; + block_security_deposit; + endorsement_security_deposit; + _ }; + _ } -> + (* find block with 32 different endorsers *) + let open Alpha_services.Delegate.Endorsing_rights in + let rec find_block b = + Context.get_endorsers (B b) + >>=? fun endorsers -> + if List.length endorsers = endorsers_per_block then return b + else Block.bake b >>=? fun b -> find_block b + in + let balance_update delegate before after = + Context.Delegate.info (B before) delegate + >>=? fun info_before -> + Context.Delegate.info (B after) delegate + >>=? fun info_after -> + Lwt.return + Test_tez.Tez.(info_after.frozen_balance -? info_before.frozen_balance) + in + find_block b + >>=? fun good_b -> + Context.get_endorsers (B good_b) + >>=? fun endorsers -> + (* test 3 different priorities, too long otherwise *) + let block_priorities = 0 -- 10 in + let included_endorsements = 0 -- endorsers_per_block in + let ranges = List.product block_priorities included_endorsements in + List.iter_es + (fun (priority, endorsing_power) -> + (* bake block at given priority and with given endorsing_power *) + let real_endorsers = List.sub endorsers endorsing_power in + List.map_ep + (fun endorser -> + Op.endorsement ~delegate:endorser.delegate (B good_b) () + >|=? fun operation -> Operation.pack operation) + real_endorsers + >>=? fun operations -> + let policy = Block.By_priority priority in + Block.get_next_baker ~policy good_b + >>=? fun (baker, _, _) -> + Block.bake ~policy ~operations good_b + >>=? fun b -> + Context.get_baking_reward (B b) ~priority ~endorsing_power + >>=? fun baking_reward -> + Test_tez.Tez.(block_security_deposit +? baking_reward) + >>?= fun baking_frozen_balance -> + Context.get_endorsing_reward (B b) ~priority ~endorsing_power:1 + >>=? fun endorsing_reward -> + Test_tez.Tez.(endorsement_security_deposit +? endorsing_reward) + >>?= fun endorsing_frozen_balance -> + let baker_is_not_an_endorser = + List.for_all + (fun endorser -> endorser.delegate <> baker) + real_endorsers + in + Test_tez.Tez.(baking_frozen_balance +? endorsing_frozen_balance) + >>?= fun accumulated_frozen_balance -> + (* check the baker was rewarded the right amount *) + balance_update baker good_b b + >>=? fun baker_frozen_balance -> + ( if baker_is_not_an_endorser then + Assert.equal_tez + ~loc:__LOC__ + baker_frozen_balance + baking_frozen_balance + else + Assert.equal_tez + ~loc:__LOC__ + baker_frozen_balance + accumulated_frozen_balance ) + >>=? fun () -> + (* check the each endorser was rewarded the right amount *) + List.iter_ep + (fun endorser -> + balance_update endorser.delegate good_b b + >>=? fun endorser_frozen_balance -> + if baker <> endorser.delegate then + Assert.equal_tez + ~loc:__LOC__ + endorser_frozen_balance + endorsing_frozen_balance + else + Assert.equal_tez + ~loc:__LOC__ + endorser_frozen_balance + accumulated_frozen_balance) + real_endorsers) + ranges + +(** Checks the baking and endorsing rewards formulas against a precomputed + table. *) +let test_rewards_formulas () = + Context.init 1 + >>=? fun (b, _) -> + Context.get_constants (B b) + >>=? fun Constants.{parametric = {endorsers_per_block; _}; _} -> + let block_priorities = 0 -- 2 in + let included_endorsements = 0 -- endorsers_per_block in + let ranges = List.product block_priorities included_endorsements in + List.iter_ep + (fun (priority, endorsing_power) -> + Context.get_baking_reward (B b) ~priority ~endorsing_power + >>=? fun reward -> + let expected_reward = + Test_tez.Tez.of_mutez_exn + (Int64.of_int Rewards.baking_rewards.(priority).(endorsing_power)) + in + Assert.equal_tez ~loc:__LOC__ reward expected_reward + >>=? fun () -> + Context.get_endorsing_reward (B b) ~priority ~endorsing_power + >>=? fun reward -> + let expected_reward = + Test_tez.Tez.of_mutez_exn + (Int64.of_int Rewards.endorsing_rewards.(priority).(endorsing_power)) + in + Assert.equal_tez ~loc:__LOC__ reward expected_reward + >>=? fun () -> return_unit) + ranges + +let wrap e = Lwt.return (Environment.wrap_tzresult e) + +(** Check that the rewards formulas from Context are equivalent with + the ones from Baking. *) +let test_rewards_formulas_equivalence () = + Context.init 1 + >>=? fun (b, _) -> + Context.get_constants (B b) + >>=? fun Constants.{parametric = {endorsers_per_block; _}; _} -> + Alpha_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun (ctxt, _) -> + let block_priorities = 0 -- 64 in + let endorsing_power = 0 -- endorsers_per_block in + let ranges = List.product block_priorities endorsing_power in + List.iter_ep + (fun (block_priority, endorsing_power) -> + Baking.baking_reward + ctxt + ~block_priority + ~included_endorsements:endorsing_power + |> wrap + >>=? fun reward1 -> + Context.get_baking_reward (B b) ~priority:block_priority ~endorsing_power + >>=? fun reward2 -> + Assert.equal_tez ~loc:__LOC__ reward1 reward2 + >>=? fun () -> + Baking.endorsing_reward ctxt ~block_priority endorsing_power + |> wrap + >>=? fun reward1 -> + Context.get_endorsing_reward + (B b) + ~priority:block_priority + ~endorsing_power + >>=? fun reward2 -> Assert.equal_tez ~loc:__LOC__ reward1 reward2) + ranges + +(** Test baking [n] cycles in a raw works smoothly. *) +let test_bake_n_cycles n () = + let open Block in + let policy = By_priority 0 in + Context.init 1 + >>=? fun (block, _contracts) -> + Block.bake_until_n_cycle_end ~policy n block >>=? fun _block -> return () + +(** Check the voting power is constant between cycles when number of + rolls are constant and in presence of one account. *) +let test_voting_power_cache () = + let open Block in + let policy = By_priority 0 in + Context.init 1 + >>=? fun (block, _contracts) -> + Context.get_bakers (B block) + >>=? fun bakers -> + let baker = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bakers in + let assert_voting_power n block = + let ctxt = Context.B block in + Context.get_voting_power ctxt baker + >>=? fun voting_power -> + Assert.equal_int ~loc:__LOC__ n (Int32.to_int voting_power) + in + assert_voting_power 500 block + >>=? fun () -> + Block.bake_until_n_cycle_end ~policy 2 block + >>=? fun block -> + assert_voting_power 500 block + >>=? fun () -> + Block.bake_until_n_cycle_end ~policy 5 block + >>=? fun block -> + assert_voting_power 500 block + >>=? fun () -> + Block.bake_until_n_cycle_end ~policy 1 block + >>=? fun block -> assert_voting_power 500 block + +let tests = + [ Test_services.tztest "cycle" `Quick test_cycle; + Test_services.tztest + "test rewards are correctly accounted for" + `Slow + test_rewards_retrieval; + Test_services.tztest + "test rewards formula for various input values" + `Quick + test_rewards_formulas; + Test_services.tztest + "check equivalence of rewards formulas" + `Quick + test_rewards_formulas_equivalence; + Test_services.tztest + "test_bake_n_cycles for 12 cycles" + `Quick + (test_bake_n_cycles 12); + Test_services.tztest "voting_power" `Quick test_voting_power_cache ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_combined_operations.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_combined_operations.ml new file mode 100644 index 0000000000000000000000000000000000000000..1c58da0b5fc4cae9be25a8a7ceb88f46fc924281 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_combined_operations.ml @@ -0,0 +1,364 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (combined operations) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^combined$" + Subject: Multiple operations can be grouped in one ensuring their + deterministic application. + + If an invalid operation is present in this group of + operations, the previously applied operations are + backtracked leaving the context unchanged and the + following operations are skipped. Fees attributed to the + operations are collected by the baker nonetheless. + + Only manager operations are allowed in multiple transactions. + They must all belong to the same manager as there is only one + signature. +*) + +open Protocol +open Test_tez + +let ten_tez = Tez.of_int 10 + +(** Groups ten transactions between the same parties. *) +let test_multiple_transfers () = + Context.init 3 + >>=? fun (blk, contracts) -> + let (c1, c2, c3) = + match contracts with [c1; c2; c3] -> (c1, c2, c3) | _ -> assert false + in + List.map_es (fun _ -> Op.transaction (B blk) c1 c2 Tez.one) (1 -- 10) + >>=? fun ops -> + Op.combine_operations ~source:c1 (B blk) ops + >>=? fun operation -> + Context.Contract.balance (B blk) c1 + >>=? fun c1_old_balance -> + Context.Contract.balance (B blk) c2 + >>=? fun c2_old_balance -> + Context.Contract.pkh c3 + >>=? fun baker_pkh -> + Block.bake ~policy:(By_account baker_pkh) ~operation blk + >>=? fun blk -> + Assert.balance_was_debited + ~loc:__LOC__ + (B blk) + c1 + c1_old_balance + (Tez.of_int 10) + >>=? fun () -> + Assert.balance_was_credited + ~loc:__LOC__ + (B blk) + c2 + c2_old_balance + (Tez.of_int 10) + >>=? fun () -> return_unit + +(** Groups ten delegated originations. *) +let test_multiple_origination_and_delegation () = + Context.init 2 + >>=? fun (blk, contracts) -> + let (c1, c2) = + match contracts with [c1; c2] -> (c1, c2) | _ -> assert false + in + let n = 10 in + Context.get_constants (B blk) + >>=? fun {parametric = {origination_size; cost_per_byte; _}; _} -> + Context.Contract.pkh c2 + >>=? fun delegate_pkh -> + (* Deploy n smart contracts with dummy scripts from c1 *) + List.map_es + (fun i -> + Op.origination + ~delegate:delegate_pkh + ~counter:(Z.of_int i) + ~fee:Tez.zero + ~script:Op.dummy_script + ~credit:(Tez.of_int 10) + (B blk) + c1) + (1 -- n) + >>=? fun originations -> + (* These computed originated contracts are not the ones really created *) + (* We will extract them from the tickets *) + let (originations_operations, _) = List.split originations in + Op.combine_operations ~source:c1 (B blk) originations_operations + >>=? fun operation -> + Context.Contract.balance (B blk) c1 + >>=? fun c1_old_balance -> + Incremental.begin_construction blk + >>=? fun inc -> + Incremental.add_operation inc operation + >>=? fun inc -> + (* To retrieve the originated contracts, it is easier to extract them + from the tickets. Else, we could (could we ?) hash each combined + operation individually. *) + let tickets = Incremental.rev_tickets inc in + let open Apply_results in + let tickets = + List.fold_left + (fun acc -> function No_operation_metadata -> assert false + | Operation_metadata {contents} -> + to_list (Contents_result_list contents) @ acc) + [] + tickets + |> List.rev + in + let new_contracts = + List.map + (function + | Contents_result + (Manager_operation_result + { operation_result = + Applied (Origination_result {originated_contracts = [h]; _}); + _ }) -> + h + | _ -> + assert false) + tickets + in + (* Previous balance - (Credit (n * 10tz) + Origination cost (n tz)) *) + Tez.(cost_per_byte *? Int64.of_int origination_size) + >>?= fun origination_burn -> + Tez.(origination_burn *? Int64.of_int n) + >>?= fun origination_total_cost -> + Tez.( *? ) Op.dummy_script_cost 10L + >>? Tez.( +? ) (Tez.of_int (10 * n)) + >>? Tez.( +? ) origination_total_cost + >>?= fun total_cost -> + Assert.balance_was_debited ~loc:__LOC__ (I inc) c1 c1_old_balance total_cost + >>=? fun () -> + List.iter_es + (fun c -> Assert.balance_is ~loc:__LOC__ (I inc) c (Tez.of_int 10)) + new_contracts + +let expect_balance_too_low = function + | Environment.Ecoproto_error (Contract_storage.Balance_too_low _) :: _ -> + return_unit + | _ -> + failwith + "Contract should not have a sufficient balance : operation expected \ + to fail." + +(** Groups three operations, the middle one failing. + Checks that the receipt is consistent. + Variant without fees. *) +let test_failing_operation_in_the_middle () = + Context.init 2 + >>=? fun (blk, contracts) -> + let (c1, c2) = + match contracts with [c1; c2] -> (c1, c2) | _ -> assert false + in + Op.transaction ~fee:Tez.zero (B blk) c1 c2 Tez.one + >>=? fun op1 -> + Op.transaction ~fee:Tez.zero (B blk) c1 c2 Tez.max_tez + >>=? fun op2 -> + Op.transaction ~fee:Tez.zero (B blk) c1 c2 Tez.one + >>=? fun op3 -> + let operations = [op1; op2; op3] in + Op.combine_operations ~source:c1 (B blk) operations + >>=? fun operation -> + Context.Contract.balance (B blk) c1 + >>=? fun c1_old_balance -> + Context.Contract.balance (B blk) c2 + >>=? fun c2_old_balance -> + Incremental.begin_construction blk + >>=? fun inc -> + Incremental.add_operation + ~expect_failure:expect_balance_too_low + inc + operation + >>=? fun inc -> + let tickets = Incremental.rev_tickets inc in + let open Apply_results in + let tickets = + List.fold_left + (fun acc -> function No_operation_metadata -> assert false + | Operation_metadata {contents} -> + to_list (Contents_result_list contents) @ acc) + [] + tickets + in + ( match tickets with + | Contents_result + (Manager_operation_result {operation_result = Backtracked _; _}) + :: Contents_result + (Manager_operation_result {operation_result = Failed (_, trace); _}) + :: Contents_result + (Manager_operation_result {operation_result = Skipped _; _}) + :: _ -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + let expect = + Format.asprintf "Balance of contract %a too low" Context.Contract.pp c1 + in + assert (Astring.String.is_infix ~affix:expect trace_string) + | _ -> + assert false ) ; + Assert.balance_is ~loc:__LOC__ (I inc) c1 c1_old_balance + >>=? fun () -> + Assert.balance_is ~loc:__LOC__ (I inc) c2 c2_old_balance + >>=? fun () -> return_unit + +(** Groups three operations, the middle one failing. + Checks that the receipt is consistent. + Variant with fees, that should be spent even in case of failure. *) +let test_failing_operation_in_the_middle_with_fees () = + Context.init 2 + >>=? fun (blk, contracts) -> + let (c1, c2) = + match contracts with [c1; c2] -> (c1, c2) | _ -> assert false + in + Op.transaction ~fee:Tez.one (B blk) c1 c2 Tez.one + >>=? fun op1 -> + Op.transaction ~fee:Tez.one (B blk) c1 c2 Tez.max_tez + >>=? fun op2 -> + Op.transaction ~fee:Tez.one (B blk) c1 c2 Tez.one + >>=? fun op3 -> + let operations = [op1; op2; op3] in + Op.combine_operations ~source:c1 (B blk) operations + >>=? fun operation -> + Context.Contract.balance (B blk) c1 + >>=? fun c1_old_balance -> + Context.Contract.balance (B blk) c2 + >>=? fun c2_old_balance -> + Incremental.begin_construction blk + >>=? fun inc -> + Incremental.add_operation + ~expect_failure:expect_balance_too_low + inc + operation + >>=? fun inc -> + let tickets = Incremental.rev_tickets inc in + let open Apply_results in + let tickets = + List.fold_left + (fun acc -> function No_operation_metadata -> assert false + | Operation_metadata {contents} -> + to_list (Contents_result_list contents) @ acc) + [] + tickets + in + ( match tickets with + | Contents_result + (Manager_operation_result {operation_result = Backtracked _; _}) + :: Contents_result + (Manager_operation_result {operation_result = Failed (_, trace); _}) + :: Contents_result + (Manager_operation_result {operation_result = Skipped _; _}) + :: _ -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + let expect = + Format.asprintf "Balance of contract %a too low" Context.Contract.pp c1 + in + assert (Astring.String.is_infix ~affix:expect trace_string) + | _ -> + assert false ) ; + (* In the presence of a failure, all the fees are collected. Even for skipped operations. *) + Assert.balance_was_debited + ~loc:__LOC__ + (I inc) + c1 + c1_old_balance + (Tez.of_int 3) + >>=? fun () -> + Assert.balance_is ~loc:__LOC__ (I inc) c2 c2_old_balance + >>=? fun () -> return_unit + +let expect_wrong_signature list = + if + List.exists + (function + | Environment.Ecoproto_error Apply.Inconsistent_sources -> + true + | _ -> + false) + list + then return_unit + else + failwith + "Packed operation has invalid source in the middle : operation expected \ + to fail." + +let test_wrong_signature_in_the_middle () = + Context.init 2 + >>=? function + | (_, []) | (_, [_]) -> + assert false + | (blk, c1 :: c2 :: _) -> + Op.transaction ~fee:Tez.one (B blk) c1 c2 Tez.one + >>=? fun op1 -> + Op.transaction ~fee:Tez.one (B blk) c2 c1 Tez.one + >>=? fun op2 -> + Incremental.begin_construction blk + >>=? fun inc -> + (* Make legit transfers, performing reveals *) + Incremental.add_operation inc op1 + >>=? fun inc -> + Incremental.add_operation inc op2 + >>=? fun inc -> + (* Cook transactions for actual test *) + Op.transaction ~fee:Tez.one (I inc) c1 c2 Tez.one + >>=? fun op1 -> + Op.transaction ~fee:Tez.one (I inc) c1 c2 Tez.one + >>=? fun op2 -> + Op.transaction ~fee:Tez.one (I inc) c1 c2 Tez.one + >>=? fun op3 -> + Op.transaction ~fee:Tez.one (I inc) c2 c1 Tez.one + >>=? fun spurious_operation -> + let operations = [op1; op2; op3] in + Op.combine_operations ~spurious_operation ~source:c1 (I inc) operations + >>=? fun operation -> + Incremental.add_operation + ~expect_apply_failure:expect_wrong_signature + inc + operation + >>=? fun _inc -> return_unit + +let tests = + [ Test_services.tztest "multiple transfers" `Quick test_multiple_transfers; + Test_services.tztest + "multiple originations and delegations" + `Quick + test_multiple_origination_and_delegation; + Test_services.tztest + "Failing operation in the middle" + `Quick + test_failing_operation_in_the_middle; + Test_services.tztest + "Failing operation in the middle (with fees)" + `Quick + test_failing_operation_in_the_middle_with_fees; + Test_services.tztest + "Failing operation (wrong manager in the middle of a pack)" + `Quick + test_wrong_signature_in_the_middle ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_delegation.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_delegation.ml new file mode 100644 index 0000000000000000000000000000000000000000..c6090c6916dd075cf1688f208ad9d32e9c8ec37e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_delegation.ml @@ -0,0 +1,1918 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (delegation) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^delegation$" + Subject: - Properties on bootstrap contracts (self-delegation, + cannot delete/change their delegate (as opposed to contracts + not-being-delegate which can do these), bootstrap manager + as delegate during origination). + - Properties on delegation depending on whether delegate + keys registration, through origination and delegation. +*) + +open Protocol +open Alpha_context +open Test_tez + +(*****************************************************************************) +(* Bootstrap contracts + ------------------- + Bootstrap contracts are heavily used in other tests. It is helpful to test + some properties of these contracts, so we can correctly interpret the other + tests that use them. *) +(*****************************************************************************) + +let expect_error err = function + | err0 :: _ when err = err0 -> + return_unit + | _ -> + failwith "Unexpected successful result" + +let expect_alpha_error err = expect_error (Environment.Ecoproto_error err) + +let expect_no_change_registered_delegate_pkh pkh = function + | Environment.Ecoproto_error (Delegate_storage.No_deletion pkh0) :: _ + when pkh0 = pkh -> + return_unit + | _ -> + failwith "Delegate can not be deleted and operation should fail." + +(** Bootstrap contracts delegate to themselves. *) +let bootstrap_manager_is_bootstrap_delegate () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + let bootstrap0 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + Context.Contract.delegate (B b) bootstrap0 + >>=? fun delegate0 -> + Context.Contract.manager (B b) bootstrap0 + >>=? fun manager0 -> Assert.equal_pkh ~loc:__LOC__ delegate0 manager0.pkh + +(** Bootstrap contracts cannot change their delegate. *) +let bootstrap_delegate_cannot_change ~fee () = + Context.init 2 + >>=? fun (b, bootstrap_contracts) -> + let bootstrap0 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth bootstrap_contracts 0 + in + let bootstrap1 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth bootstrap_contracts 1 + in + Context.Contract.pkh bootstrap0 + >>=? fun pkh1 -> + Incremental.begin_construction b ~policy:(Block.Excluding [pkh1]) + >>=? fun i -> + Context.Contract.manager (I i) bootstrap1 + >>=? fun manager1 -> + Context.Contract.balance (I i) bootstrap0 + >>=? fun balance0 -> + Context.Contract.delegate (I i) bootstrap0 + >>=? fun delegate0 -> + (* change delegation to bootstrap1 *) + Op.delegation ~fee (I i) bootstrap0 (Some manager1.pkh) + >>=? fun set_delegate -> + if fee > balance0 then + Incremental.add_operation i set_delegate + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + Incremental.add_operation + ~expect_failure:(expect_no_change_registered_delegate_pkh delegate0) + i + set_delegate + >>=? fun i -> + Incremental.finalize_block i + >>=? fun b -> + (* bootstrap0 still has same delegate *) + Context.Contract.delegate (B b) bootstrap0 + >>=? fun delegate0_after -> + Assert.equal_pkh ~loc:__LOC__ delegate0_after delegate0 + >>=? fun () -> + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (B b) bootstrap0 balance0 fee + +(** Bootstrap contracts cannot delete their delegation. *) +let bootstrap_delegate_cannot_be_removed ~fee () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + Incremental.begin_construction b + >>=? fun i -> + Context.Contract.balance (I i) bootstrap + >>=? fun balance -> + Context.Contract.delegate (I i) bootstrap + >>=? fun delegate -> + Context.Contract.manager (I i) bootstrap + >>=? fun manager -> + (* remove delegation *) + Op.delegation ~fee (I i) bootstrap None + >>=? fun set_delegate -> + if fee > balance then + Incremental.add_operation i set_delegate + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + Incremental.add_operation + ~expect_failure:(expect_no_change_registered_delegate_pkh manager.pkh) + i + set_delegate + >>=? fun i -> + (* delegate has not changed *) + Context.Contract.delegate (I i) bootstrap + >>=? fun delegate_after -> + Assert.equal_pkh ~loc:__LOC__ delegate delegate_after + >>=? fun () -> + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + +(** Contracts not registered as delegate can change their + delegation. *) +let delegate_can_be_changed_from_unregistered_contract ~fee () = + Context.init 2 + >>=? fun (b, bootstrap_contracts) -> + let bootstrap0 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let bootstrap1 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth bootstrap_contracts 1 + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let unregistered = Contract.implicit_contract unregistered_pkh in + Incremental.begin_construction b + >>=? fun i -> + Context.Contract.manager (I i) bootstrap0 + >>=? fun manager0 -> + Context.Contract.manager (I i) bootstrap1 + >>=? fun manager1 -> + let credit = Tez.of_int 10 in + Op.transaction ~fee:Tez.zero (I i) bootstrap0 unregistered credit + >>=? fun credit_contract -> + Context.Contract.balance (I i) bootstrap0 + >>=? fun balance -> + Incremental.add_operation i credit_contract + >>=? fun i -> + (* delegate to bootstrap0 *) + Op.delegation ~fee:Tez.zero (I i) unregistered (Some manager0.pkh) + >>=? fun set_delegate -> + Incremental.add_operation i set_delegate + >>=? fun i -> + Context.Contract.delegate (I i) unregistered + >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager0.pkh + >>=? fun () -> + (* change delegation to bootstrap1 *) + Op.delegation ~fee (I i) unregistered (Some manager1.pkh) + >>=? fun change_delegate -> + if fee > balance then + Incremental.add_operation i change_delegate + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + Incremental.add_operation i change_delegate + >>=? fun i -> + (* delegate has changed *) + Context.Contract.delegate (I i) unregistered + >>=? fun delegate_after -> + Assert.equal_pkh ~loc:__LOC__ delegate_after manager1.pkh + >>=? fun () -> + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) unregistered credit fee + +(** Contracts not registered as delegate can delete their + delegation. *) +let delegate_can_be_removed_from_unregistered_contract ~fee () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let unregistered = Contract.implicit_contract unregistered_pkh in + Incremental.begin_construction b + >>=? fun i -> + Context.Contract.manager (I i) bootstrap + >>=? fun manager -> + let credit = Tez.of_int 10 in + Op.transaction ~fee:Tez.zero (I i) bootstrap unregistered credit + >>=? fun credit_contract -> + Context.Contract.balance (I i) bootstrap + >>=? fun balance -> + Incremental.add_operation i credit_contract + >>=? fun i -> + (* delegate to bootstrap *) + Op.delegation ~fee:Tez.zero (I i) unregistered (Some manager.pkh) + >>=? fun set_delegate -> + Incremental.add_operation i set_delegate + >>=? fun i -> + Context.Contract.delegate (I i) unregistered + >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh + >>=? fun () -> + (* remove delegation *) + Op.delegation ~fee (I i) unregistered None + >>=? fun delete_delegate -> + if fee > balance then + Incremental.add_operation i delete_delegate + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + Incremental.add_operation i delete_delegate + >>=? fun i -> + (* the delegate has been removed *) + Context.Contract.delegate_opt (I i) unregistered + >>=? (function + | None -> + return_unit + | Some _ -> + failwith "Expected delegate to be removed") + >>=? fun () -> + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) unregistered credit fee + +(** Bootstrap keys are already registered as delegate keys. *) +let bootstrap_manager_already_registered_delegate ~fee () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + Context.Contract.manager (I i) bootstrap + >>=? fun manager -> + let pkh = manager.pkh in + let impl_contract = Contract.implicit_contract pkh in + Context.Contract.balance (I i) impl_contract + >>=? fun balance -> + Op.delegation ~fee (I i) impl_contract (Some pkh) + >>=? fun sec_reg -> + if fee > balance then + Incremental.add_operation i sec_reg + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + Incremental.add_operation + ~expect_failure:(function + | Environment.Ecoproto_error Delegate_storage.Active_delegate :: _ -> + return_unit + | _ -> + failwith "Delegate is already active and operation should fail.") + i + sec_reg + >>=? fun i -> + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract balance fee + +(** Bootstrap manager can be set as delegate of an originated contract + (through origination operation). *) +let delegate_to_bootstrap_by_origination ~fee () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + Context.Contract.manager (I i) bootstrap + >>=? fun manager -> + Context.Contract.balance (I i) bootstrap + >>=? fun balance -> + (* originate a contract with bootstrap's manager as delegate *) + Op.origination + ~fee + ~credit:Tez.zero + ~delegate:manager.pkh + (I i) + bootstrap + ~script:Op.dummy_script + >>=? fun (op, orig_contract) -> + Context.get_constants (I i) + >>=? fun {parametric = {origination_size; cost_per_byte; _}; _} -> + (* 0.257tz *) + Tez.(cost_per_byte *? Int64.of_int origination_size) + >>?= fun origination_burn -> + Tez.( +? ) fee origination_burn + >>? Tez.( +? ) Op.dummy_script_cost + >>?= fun total_fee -> + if fee > balance then + Incremental.add_operation i op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else if total_fee > balance && balance >= fee then + (* origination did not proceed; fee has been debited *) + Incremental.add_operation + i + ~expect_failure:(function + | Environment.Ecoproto_error (Contract.Balance_too_low _) :: _ -> + return_unit + | _ -> + failwith + "Not enough balance for origination burn: operation should fail.") + op + >>=? fun i -> + (* fee was taken *) + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + >>=? fun () -> + (* originated contract has not been created *) + Context.Contract.balance (I i) orig_contract + >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> + true + | _ -> + false) + else + (* bootstrap is delegate, fee + origination burn have been debited *) + Incremental.add_operation i op + >>=? fun i -> + Context.Contract.delegate (I i) orig_contract + >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh + >>=? fun () -> + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance total_fee + +let tests_bootstrap_contracts = + [ Test_services.tztest + "bootstrap contracts delegate to themselves" + `Quick + bootstrap_manager_is_bootstrap_delegate; + Test_services.tztest + "bootstrap contracts can change their delegate (small fee)" + `Quick + (bootstrap_delegate_cannot_change ~fee:Tez.one_mutez); + Test_services.tztest + "bootstrap contracts can change their delegate (max fee)" + `Quick + (bootstrap_delegate_cannot_change ~fee:Tez.max_tez); + Test_services.tztest + "bootstrap contracts cannot remove their delegation (small fee)" + `Quick + (bootstrap_delegate_cannot_be_removed ~fee:Tez.one_mutez); + Test_services.tztest + "bootstrap contracts cannot remove their delegation (max fee)" + `Quick + (bootstrap_delegate_cannot_be_removed ~fee:Tez.max_tez); + Test_services.tztest + "contracts not registered as delegate can remove their delegation \ + (small fee)" + `Quick + (delegate_can_be_changed_from_unregistered_contract ~fee:Tez.one_mutez); + Test_services.tztest + "contracts not registered as delegate can remove their delegation (max \ + fee)" + `Quick + (delegate_can_be_changed_from_unregistered_contract ~fee:Tez.max_tez); + Test_services.tztest + "contracts not registered as delegate can remove their delegation \ + (small fee)" + `Quick + (delegate_can_be_removed_from_unregistered_contract ~fee:Tez.one_mutez); + Test_services.tztest + "contracts not registered as delegate can remove their delegation (max \ + fee)" + `Quick + (delegate_can_be_removed_from_unregistered_contract ~fee:Tez.max_tez); + Test_services.tztest + "bootstrap keys are already registered as delegate keys (small fee)" + `Quick + (bootstrap_manager_already_registered_delegate ~fee:Tez.one_mutez); + Test_services.tztest + "bootstrap keys are already registered as delegate keys (max fee)" + `Quick + (bootstrap_manager_already_registered_delegate ~fee:Tez.max_tez); + Test_services.tztest + "bootstrap manager can be delegate (init origination, small fee)" + `Quick + (delegate_to_bootstrap_by_origination ~fee:Tez.one_mutez); + (* balance enough for fee but not for fee + origination burn + dummy script storage cost *) + Test_services.tztest + "bootstrap manager can be delegate (init origination, edge case)" + `Quick + (delegate_to_bootstrap_by_origination + ~fee:(Tez.of_mutez_exn 3_999_999_705_000L)); + (* fee bigger than bootstrap's initial balance*) + Test_services.tztest + "bootstrap manager can be delegate (init origination, large fee)" + `Quick + (delegate_to_bootstrap_by_origination ~fee:(Tez.of_int 10_000_000)) ] + +(*****************************************************************************) +(* Delegate registration + --------------------- + A delegate is a pkh. Delegates must be registered. Registration is + done via the self-delegation of the implicit contract corresponding + to the pkh. The implicit contract must be credited when the + self-delegation is done. Furthermore, trying to register an already + registered key raises an error. + + In this series of tests, we verify that + 1- unregistered delegate keys cannot be delegated to, + 2- registered keys can be delegated to, + 3- registering an already registered key raises an error. + + We consider three scenarios for setting a delegate: + - through origination, + - through delegation when the implicit contract has no delegate yet, + - through delegation when the implicit contract already has a delegate. + + We also test that emptying the implicit contract linked to a + registered delegate key does not unregister the delegate key. + + Valid registration + ------------------ + Unregistered key: + - contract not credited and no self-delegation, + - contract credited but no self-delegation, + - contract not credited and self-delegation. + + Not credited: + - no credit operation + - credit operation of 1μꜩ and then debit operation of 1μꜩ *) +(*****************************************************************************) + +(* Part A. + Unregistered delegate keys cannot be used for delegation + + Two main series of tests: without self-delegation and with a failed attempt at self-delegation: + + 1/ no self-delegation + a/ no credit + - no token transfer + - credit of 1μꜩ and then debit of 1μꜩ + b/ with credit of 1μꜩ. + For every scenario, we try three different ways of delegating: + - through origination (init origination) + - through delegation when no delegate was assigned (init delegation) + - through delegation when a delegate was assigned (switch delegation). + + 2/ Self-delegation fails if the contract has no credit. We try the + two possibilities of 1a for non-credited contracts. *) + +let expect_unregistered_key pkh = function + | Environment.Ecoproto_error (Roll_storage.Unregistered_delegate pkh0) :: _ + when pkh = pkh0 -> + return_unit + | _ -> + failwith "Delegate key is not registered: operation should fail." + +(* Part A. Section 1. + No self-delegation. *) + +(** No token transfer, no self-delegation. Originated account. If + fees are higher than balance, [Balance_too_low] is + raised. Otherwise, it checks the correct exception is raised + (unregistered key), and the fees are still debited. Using RPCs, we + verify the contract has not been originated. *) +let test_unregistered_delegate_key_init_origination ~fee () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + (* origination with delegate argument *) + Op.origination + ~fee + ~delegate:unregistered_pkh + (I i) + bootstrap + ~script:Op.dummy_script + >>=? fun (op, orig_contract) -> + Context.get_constants (I i) + >>=? fun {parametric = {origination_size; cost_per_byte; _}; _} -> + Tez.(cost_per_byte *? Int64.of_int origination_size) + >>?= fun origination_burn -> + Tez.( +? ) fee origination_burn + >>?= fun _total_fee -> + (* FIXME unused variable *) + Context.Contract.balance (I i) bootstrap + >>=? fun balance -> + if fee > balance then + Incremental.add_operation i op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* origination did not proceed; fee has been debited *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i + op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + >>=? fun () -> + (* originated contract has not been created *) + Context.Contract.balance (I i) orig_contract + >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> + true + | _ -> + false) + +(** Delegation when delegate key is not assigned. Delegate account is + initialized. If fees are higher than initial credit (10 tez), + [Balance_too_low] is raised. Otherwise, fees are still debited. The + implicit contract has no delegate. *) +let test_unregistered_delegate_key_init_delegation ~fee () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = + Account.(unregistered_delegate_account.pkh) + in + (* initial credit for the delegated contract *) + let credit = Tez.of_int 10 in + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract credit + >>=? fun credit_contract -> + Incremental.add_operation i credit_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract credit + >>=? fun _ -> + (* try to delegate *) + Op.delegation ~fee (I i) impl_contract (Some unregistered_delegate_pkh) + >>=? fun delegate_op -> + if fee > credit then + Incremental.add_operation i delegate_op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* fee has been debited; no delegate *) + Incremental.add_operation + i + ~expect_failure:(expect_unregistered_key unregistered_delegate_pkh) + delegate_op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract credit fee + >>=? fun () -> + (* implicit contract has no delegate *) + Context.Contract.delegate (I i) impl_contract + >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> + true + | _ -> + false) + +(** Re-delegation when a delegate key was already assigned. If fees + are higher than initial credit (10 tez), [Balance_too_low] is + raised. Otherwise, fees are not debited and the implicit contract + delegate remains unchanged. *) +let test_unregistered_delegate_key_switch_delegation ~fee () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let bootstrap_pkh = + Contract.is_implicit bootstrap |> WithExceptions.Option.get ~loc:__LOC__ + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = + Account.(unregistered_delegate_account.pkh) + in + (* initial credit for the delegated contract *) + let credit = Tez.of_int 10 in + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract credit + >>=? fun init_credit -> + Incremental.add_operation i init_credit + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract credit + >>=? fun _ -> + (* set and check the initial delegate *) + Op.delegation ~fee:Tez.zero (I i) impl_contract (Some bootstrap_pkh) + >>=? fun delegate_op -> + Incremental.add_operation i delegate_op + >>=? fun i -> + Context.Contract.delegate (I i) bootstrap + >>=? fun delegate_pkh -> + Assert.equal_pkh ~loc:__LOC__ bootstrap_pkh delegate_pkh + >>=? fun () -> + (* try to delegate *) + Op.delegation ~fee (I i) impl_contract (Some unregistered_delegate_pkh) + >>=? fun delegate_op -> + if fee > credit then + Incremental.add_operation i delegate_op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* fee has been debited; no delegate *) + Incremental.add_operation + i + ~expect_failure:(expect_unregistered_key unregistered_delegate_pkh) + delegate_op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract credit fee + >>=? fun () -> + (* implicit contract delegate has not changed *) + Context.Contract.delegate (I i) bootstrap + >>=? fun delegate_pkh_after -> + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate_pkh_after + +(** Same as [unregistered_delegate_key_init_origination] and credits + [amount], no self-delegation. *) +let test_unregistered_delegate_key_init_origination_credit ~fee ~amount () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* origination with delegate argument *) + Context.Contract.balance (I i) bootstrap + >>=? fun balance -> + Op.origination + ~fee + ~delegate:unregistered_pkh + (I i) + bootstrap + ~script:Op.dummy_script + >>=? fun (op, orig_contract) -> + if fee > balance then + Incremental.add_operation i op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* origination not done, fee taken *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i + op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + >>=? fun () -> + Context.Contract.balance (I i) orig_contract + >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> + true + | _ -> + false) + +(** Same as [unregistered_delegate_key_init_delegation] and credits + the amount [amount] of the implicit contract. *) +let test_unregistered_delegate_key_init_delegation_credit ~fee ~amount () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = + Account.(unregistered_delegate_account.pkh) + in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* initial credit for the delegated contract *) + let credit = Tez.of_int 10 in + Tez.(credit +? amount) + >>?= fun balance -> + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract credit + >>=? fun init_credit -> + Incremental.add_operation i init_credit + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract balance + >>=? fun _ -> + (* try to delegate *) + Op.delegation ~fee (I i) impl_contract (Some unregistered_delegate_pkh) + >>=? fun delegate_op -> + if fee > credit then + Incremental.add_operation i delegate_op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* fee has been taken, no delegate for contract *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_delegate_pkh) + i + delegate_op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract balance fee + >>=? fun () -> + Context.Contract.delegate (I i) impl_contract + >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> + true + | _ -> + false) + +(** Same as in [unregistered_delegate_key_switch_delegation] and + credits the amount [amount] to the implicit contract. *) +let test_unregistered_delegate_key_switch_delegation_credit ~fee ~amount () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let bootstrap_pkh = + Contract.is_implicit bootstrap |> WithExceptions.Option.get ~loc:__LOC__ + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = + Account.(unregistered_delegate_account.pkh) + in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* initial credit for the delegated contract *) + let credit = Tez.of_int 10 in + Tez.(credit +? amount) + >>?= fun balance -> + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract credit + >>=? fun init_credit -> + Incremental.add_operation i init_credit + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract balance + >>=? fun _ -> + (* set and check the initial delegate *) + Op.delegation ~fee:Tez.zero (I i) impl_contract (Some bootstrap_pkh) + >>=? fun delegate_op -> + Incremental.add_operation i delegate_op + >>=? fun i -> + Context.Contract.delegate (I i) bootstrap + >>=? fun delegate_pkh -> + Assert.equal_pkh ~loc:__LOC__ bootstrap_pkh delegate_pkh + >>=? fun () -> + (* switch delegate through delegation *) + Op.delegation ~fee (I i) impl_contract (Some unregistered_delegate_pkh) + >>=? fun delegate_op -> + if fee > credit then + Incremental.add_operation i delegate_op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* fee has been taken, delegate for contract has not changed *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_delegate_pkh) + i + delegate_op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract balance fee + >>=? fun () -> + Context.Contract.delegate (I i) impl_contract + >>=? fun delegate -> + Assert.not_equal_pkh ~loc:__LOC__ delegate unregistered_delegate_pkh + >>=? fun () -> Assert.equal_pkh ~loc:__LOC__ delegate bootstrap_pkh + +(** A credit of some amount followed by a debit of the same amount, + no self-delegation. *) +let test_unregistered_delegate_key_init_origination_credit_debit ~fee ~amount + () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit + check balance *) + Op.transaction (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* debit + check balance *) + Op.transaction (I i) impl_contract bootstrap amount + >>=? fun debit_contract -> + Incremental.add_operation i debit_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero + >>=? fun _ -> + (* origination with delegate argument *) + Context.Contract.balance (I i) bootstrap + >>=? fun balance -> + Op.origination + ~fee + ~delegate:unregistered_pkh + (I i) + bootstrap + ~script:Op.dummy_script + >>=? fun (op, orig_contract) -> + if fee > balance then + Incremental.add_operation i op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* fee taken, origination not processed *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i + op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + >>=? fun () -> + Context.Contract.balance (I i) orig_contract + >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> + true + | _ -> + false) + +(** Same as in [unregistered_delegate_key_init_delegation] but credits + then debits the amount [amount] to the implicit contract. *) +let test_unregistered_delegate_key_init_delegation_credit_debit ~amount ~fee () + = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = + Account.(unregistered_delegate_account.pkh) + in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* debit + check balance *) + Op.transaction ~fee:Tez.zero (I i) impl_contract bootstrap amount + >>=? fun debit_contract -> + Incremental.add_operation i debit_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero + >>=? fun _ -> + (* initial credit for the delegated contract *) + let credit = Tez.of_int 10 in + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract credit + >>=? fun credit_contract -> + Incremental.add_operation i credit_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract credit + >>=? fun _ -> + (* try to delegate *) + Op.delegation ~fee (I i) impl_contract (Some unregistered_delegate_pkh) + >>=? fun delegate_op -> + if fee > credit then + Incremental.add_operation i delegate_op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* fee has been taken, no delegate for contract *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_delegate_pkh) + i + delegate_op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract credit fee + >>=? fun () -> + Context.Contract.delegate (I i) impl_contract + >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> + true + | _ -> + false) + +(** Same as in [unregistered_delegate_key_switch_delegation] but + credits then debits the amount [amount] to the implicit contract. *) +let test_unregistered_delegate_key_switch_delegation_credit_debit ~fee ~amount + () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let bootstrap_pkh = + Contract.is_implicit bootstrap |> WithExceptions.Option.get ~loc:__LOC__ + in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = + Account.(unregistered_delegate_account.pkh) + in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* debit + check balance *) + Op.transaction (I i) impl_contract bootstrap amount + >>=? fun debit_contract -> + Incremental.add_operation i debit_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero + >>=? fun _ -> + (* delegation - initial credit for the delegated contract *) + let credit = Tez.of_int 10 in + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract credit + >>=? fun credit_contract -> + Incremental.add_operation i credit_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract credit + >>=? fun _ -> + (* set and check the initial delegate *) + Op.delegation ~fee:Tez.zero (I i) impl_contract (Some bootstrap_pkh) + >>=? fun delegate_op -> + Incremental.add_operation i delegate_op + >>=? fun i -> + Context.Contract.delegate (I i) bootstrap + >>=? fun delegate_pkh -> + Assert.equal_pkh ~loc:__LOC__ bootstrap_pkh delegate_pkh + >>=? fun () -> + (* switch delegate through delegation *) + Op.delegation (I i) ~fee impl_contract (Some unregistered_delegate_pkh) + >>=? fun delegate_op -> + if fee > credit then + Incremental.add_operation i delegate_op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* fee has been taken, delegate for contract has not changed *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_delegate_pkh) + i + delegate_op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract credit fee + >>=? fun () -> + Context.Contract.delegate (I i) impl_contract + >>=? fun delegate -> + Assert.not_equal_pkh ~loc:__LOC__ delegate unregistered_delegate_pkh + +(* Part A. Section 2. + Self-delegation to an empty contract fails. *) + +(** Self-delegation with zero-balance contract should fail. *) +let test_failed_self_delegation_no_transaction () = + Context.init 1 + >>=? fun (b, _) -> + Incremental.begin_construction b + >>=? fun i -> + let account = Account.new_account () in + let unregistered_pkh = Account.(account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* check balance *) + Context.Contract.balance (I i) impl_contract + >>=? fun balance -> + Assert.equal_tez ~loc:__LOC__ Tez.zero balance + >>=? fun _ -> + (* self delegation fails *) + Op.delegation (I i) impl_contract (Some unregistered_pkh) + >>=? fun self_delegation -> + Incremental.add_operation i self_delegation + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Empty_implicit_contract pkh -> + if pkh = unregistered_pkh then true else false + | _ -> + false) + +(** Implicit contract is credited then debited of same amount (i.e., + is emptied). Self-delegation fails. *) +let test_failed_self_delegation_emptied_implicit_contract amount () = + (* create an implicit contract *) + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let account = Account.new_account () in + let unregistered_pkh = Account.(account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit implicit contract and check balance *) + Op.transaction (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* empty implicit contract and check balance *) + Op.transaction (I i) impl_contract bootstrap amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero + >>=? fun _ -> + (* self delegation fails *) + Op.delegation (I i) impl_contract (Some unregistered_pkh) + >>=? fun self_delegation -> + Incremental.add_operation i self_delegation + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Empty_implicit_contract pkh -> + if pkh = unregistered_pkh then true else false + | _ -> + false) + +(** Implicit contract is credited with a non-zero quantity [amount] + tz, then it is delegated. The operation of debit of [amount] tz + should fail as the contract is already delegated. *) +let test_emptying_delegated_implicit_contract_fails amount () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + Context.Contract.manager (I i) bootstrap + >>=? fun bootstrap_manager -> + let account = Account.new_account () in + let unregistered_pkh = Account.(account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit unregistered implicit contract and check balance *) + Op.transaction (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* delegate the contract to the bootstrap *) + Op.delegation (I i) impl_contract (Some bootstrap_manager.pkh) + >>=? fun delegation -> + Incremental.add_operation i delegation + >>=? fun i -> + (* empty implicit contract and expect error since the contract is delegated *) + Op.transaction (I i) impl_contract bootstrap amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Empty_implicit_delegated_contract _ -> + true + | _ -> + false) + +(* Part B. + - Valid registration: + - Credit implicit contract with some ꜩ + verification of balance + - Self delegation + verification + - Empty contract + verification of balance + verification of not being erased / self-delegation + - Create delegator implicit contract w first implicit contract as delegate + verification of delegation. *) + +(** Initialized account is credited of [amount] tz, then + self-delegated. *) +let test_valid_delegate_registration_init_delegation_credit amount () = + (* create an implicit contract *) + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ + check balance *) + Op.transaction (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) + >>=? fun self_delegation -> + Incremental.add_operation i self_delegation + >>=? fun i -> + Context.Contract.delegate (I i) impl_contract + >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate delegate_pkh + >>=? fun _ -> + (* create an implicit contract with no delegate *) + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let delegator = Contract.implicit_contract unregistered_pkh in + Op.transaction ~fee:Tez.zero (I i) bootstrap delegator Tez.one + >>=? fun credit_contract -> + Incremental.add_operation i credit_contract + >>=? fun i -> + (* check no delegate for delegator contract *) + Context.Contract.delegate (I i) delegator + >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> + true + | _ -> + false) + >>=? fun _ -> + (* delegation to the newly registered key *) + Op.delegation (I i) delegator (Some delegate_account.pkh) + >>=? fun delegation -> + Incremental.add_operation i delegation + >>=? fun i -> + (* check delegation *) + Context.Contract.delegate (I i) delegator + >>=? fun delegator_delegate -> + Assert.equal_pkh ~loc:__LOC__ delegator_delegate delegate_pkh + +(** Create an implicit contract, credits with [amount] + tz. Self-delegates. Create another implicit contract with + bootstrap as delegate. Re-delegate it to the first implicit + contract. *) +let test_valid_delegate_registration_switch_delegation_credit amount () = + (* create an implicit contract *) + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ + check balance *) + Op.transaction (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) + >>=? fun self_delegation -> + Incremental.add_operation i self_delegation + >>=? fun i -> + Context.Contract.delegate (I i) impl_contract + >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate delegate_pkh + >>=? fun _ -> + (* create an implicit contract with bootstrap's account as delegate *) + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let delegator = Contract.implicit_contract unregistered_pkh in + Op.transaction ~fee:Tez.zero (I i) bootstrap delegator Tez.one + >>=? fun credit_contract -> + Incremental.add_operation i credit_contract + >>=? fun i -> + Context.Contract.manager (I i) bootstrap + >>=? fun bootstrap_manager -> + Op.delegation (I i) delegator (Some bootstrap_manager.pkh) + >>=? fun delegation -> + Incremental.add_operation i delegation + >>=? fun i -> + (* test delegate of new contract is bootstrap *) + Context.Contract.delegate (I i) delegator + >>=? fun delegator_delegate -> + Assert.equal_pkh ~loc:__LOC__ delegator_delegate bootstrap_manager.pkh + >>=? fun _ -> + (* delegation with newly registered key *) + Op.delegation (I i) delegator (Some delegate_account.pkh) + >>=? fun delegation -> + Incremental.add_operation i delegation + >>=? fun i -> + Context.Contract.delegate (I i) delegator + >>=? fun delegator_delegate -> + Assert.equal_pkh ~loc:__LOC__ delegator_delegate delegate_pkh + +(** Create an implicit contract. *) +let test_valid_delegate_registration_init_delegation_credit_debit amount () = + (* create an implicit contract *) + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ+ check balance *) + Op.transaction (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) + >>=? fun self_delegation -> + Incremental.add_operation i self_delegation + >>=? fun i -> + Context.Contract.delegate (I i) impl_contract + >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate + >>=? fun _ -> + (* empty implicit contracts are usually deleted but they are kept if + they were registered as delegates. we empty the contract in + order to verify this. *) + Op.transaction (I i) impl_contract bootstrap amount + >>=? fun empty_contract -> + Incremental.add_operation i empty_contract + >>=? fun i -> + (* impl_contract is empty *) + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero + >>=? fun _ -> + (* verify self-delegation after contract is emptied *) + Context.Contract.delegate (I i) impl_contract + >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate + >>=? fun _ -> + (* create an implicit contract with no delegate *) + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let delegator = Contract.implicit_contract unregistered_pkh in + Op.transaction ~fee:Tez.zero (I i) bootstrap delegator Tez.one + >>=? fun credit_contract -> + Incremental.add_operation i credit_contract + >>=? fun i -> + (* check no delegate for delegator contract *) + Context.Contract.delegate (I i) delegator + >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> + true + | _ -> + false) + >>=? fun _ -> + (* delegation to the newly registered key *) + Op.delegation (I i) delegator (Some delegate_account.pkh) + >>=? fun delegation -> + Incremental.add_operation i delegation + >>=? fun i -> + (* check delegation *) + Context.Contract.delegate (I i) delegator + >>=? fun delegator_delegate -> + Assert.equal_pkh ~loc:__LOC__ delegator_delegate delegate_pkh + +(** A created implicit contract is credited with [amount] tz, then is + self-delegated. It is emptied (fund back into bootstrap), and + should remain existing (as registered as delegate). Another created + implicit contract is delegated to bootstrap, then should be able to + be re-delegated to the latter contract. *) +let test_valid_delegate_registration_switch_delegation_credit_debit amount () = + (* create an implicit contract *) + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ + check balance *) + Op.transaction (I i) bootstrap impl_contract amount + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount + >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) + >>=? fun self_delegation -> + Incremental.add_operation i self_delegation + >>=? fun i -> + Context.Contract.delegate (I i) impl_contract + >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate + >>=? fun _ -> + (* empty implicit contracts are usually deleted but they are kept if + they were registered as delegates. we empty the contract in + order to verify this. *) + Op.transaction (I i) impl_contract bootstrap amount + >>=? fun empty_contract -> + Incremental.add_operation i empty_contract + >>=? fun i -> + (* impl_contract is empty *) + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero + >>=? fun _ -> + (* create an implicit contract with bootstrap's account as delegate *) + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let delegator = Contract.implicit_contract unregistered_pkh in + Op.transaction ~fee:Tez.zero (I i) bootstrap delegator Tez.one + >>=? fun credit_contract -> + Incremental.add_operation i credit_contract + >>=? fun i -> + Context.Contract.manager (I i) bootstrap + >>=? fun bootstrap_manager -> + Op.delegation (I i) delegator (Some bootstrap_manager.pkh) + >>=? fun delegation -> + Incremental.add_operation i delegation + >>=? fun i -> + (* test delegate of new contract is bootstrap *) + Context.Contract.delegate (I i) delegator + >>=? fun delegator_delegate -> + Assert.equal_pkh ~loc:__LOC__ delegator_delegate bootstrap_manager.pkh + >>=? fun _ -> + (* delegation with newly registered key *) + Op.delegation (I i) delegator (Some delegate_account.pkh) + >>=? fun delegation -> + Incremental.add_operation i delegation + >>=? fun i -> + Context.Contract.delegate (I i) delegator + >>=? fun delegator_delegate -> + Assert.equal_pkh ~loc:__LOC__ delegator_delegate delegate_pkh + +(* Part C. + A second self-delegation should raise an [Active_delegate] error. *) + +(** Second self-delegation should fail with implicit contract with + some credit. *) +let test_double_registration () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let account = Account.new_account () in + let pkh = Account.(account.pkh) in + let impl_contract = Contract.implicit_contract pkh in + (* credit 1μꜩ+ check balance *) + Op.transaction (I i) bootstrap impl_contract Tez.one_mutez + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.one_mutez + >>=? fun _ -> + (* self-delegation *) + Op.delegation (I i) impl_contract (Some pkh) + >>=? fun self_delegation -> + Incremental.add_operation i self_delegation + >>=? fun i -> + (* second self-delegation *) + Op.delegation (I i) impl_contract (Some pkh) + >>=? fun second_registration -> + Incremental.add_operation i second_registration + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_storage.Active_delegate -> + true + | _ -> + false) + +(** Second self-delegation should fail with implicit contract emptied + after first self-delegation. *) +let test_double_registration_when_empty () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let account = Account.new_account () in + let pkh = Account.(account.pkh) in + let impl_contract = Contract.implicit_contract pkh in + (* credit 1μꜩ+ check balance *) + Op.transaction (I i) bootstrap impl_contract Tez.one_mutez + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.one_mutez + >>=? fun _ -> + (* self delegation *) + Op.delegation (I i) impl_contract (Some pkh) + >>=? fun self_delegation -> + Incremental.add_operation i self_delegation + >>=? fun i -> + (* empty the delegate account *) + Op.transaction (I i) impl_contract bootstrap Tez.one_mutez + >>=? fun empty_contract -> + Incremental.add_operation i empty_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero + >>=? fun _ -> + (* second self-delegation *) + Op.delegation (I i) impl_contract (Some pkh) + >>=? fun second_registration -> + Incremental.add_operation i second_registration + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_storage.Active_delegate -> + true + | _ -> + false) + +(** Second self-delegation should fail with implicit contract emptied + then credited back after first self-delegation. *) +let test_double_registration_when_recredited () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let account = Account.new_account () in + let pkh = Account.(account.pkh) in + let impl_contract = Contract.implicit_contract pkh in + (* credit 1μꜩ+ check balance *) + Op.transaction (I i) bootstrap impl_contract Tez.one_mutez + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.one_mutez + >>=? fun _ -> + (* self delegation *) + Op.delegation (I i) impl_contract (Some pkh) + >>=? fun self_delegation -> + Incremental.add_operation i self_delegation + >>=? fun i -> + (* empty the delegate account *) + Op.transaction (I i) impl_contract bootstrap Tez.one_mutez + >>=? fun empty_contract -> + Incremental.add_operation i empty_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero + >>=? fun _ -> + (* credit 1μꜩ+ check balance *) + Op.transaction (I i) bootstrap impl_contract Tez.one_mutez + >>=? fun create_contract -> + Incremental.add_operation i create_contract + >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.one_mutez + >>=? fun _ -> + (* second self-delegation *) + Op.delegation (I i) impl_contract (Some pkh) + >>=? fun second_registration -> + Incremental.add_operation i second_registration + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_storage.Active_delegate -> + true + | _ -> + false) + +(** Self-delegation on unrevealed contract. *) +let test_unregistered_and_unrevealed_self_delegate_key_init_delegation ~fee () + = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let {Account.pkh; _} = Account.new_account () in + let {Account.pkh = delegate_pkh; _} = Account.new_account () in + let contract = Alpha_context.Contract.implicit_contract pkh in + Op.transaction (I i) bootstrap contract (Tez.of_int 10) + >>=? fun op -> + Incremental.add_operation i op + >>=? fun i -> + Op.delegation ~fee (I i) contract (Some delegate_pkh) + >>=? fun op -> + Context.Contract.balance (I i) contract + >>=? fun balance -> + if fee > balance then + Incremental.add_operation i op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* origination did not proceed; fee has been debited *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key delegate_pkh) + i + op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) contract balance fee + +(** Self-delegation on revealed but not registered contract. *) +let test_unregistered_and_revealed_self_delegate_key_init_delegation ~fee () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let {Account.pkh; pk; _} = Account.new_account () in + let {Account.pkh = delegate_pkh; _} = Account.new_account () in + let contract = Alpha_context.Contract.implicit_contract pkh in + Op.transaction (I i) bootstrap contract (Tez.of_int 10) + >>=? fun op -> + Incremental.add_operation i op + >>=? fun i -> + Op.revelation (I i) pk + >>=? fun op -> + Incremental.add_operation i op + >>=? fun i -> + Op.delegation ~fee (I i) contract (Some delegate_pkh) + >>=? fun op -> + Context.Contract.balance (I i) contract + >>=? fun balance -> + if fee > balance then + Incremental.add_operation i op + >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + else + (* origination did not proceed; fee has been debited *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key delegate_pkh) + i + op + >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) contract balance fee + +(** Self-delegation on revealed and registered contract. *) +let test_registered_self_delegate_key_init_delegation () = + Context.init 1 + >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b + >>=? fun i -> + let bootstrap = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bootstrap_contracts + in + let {Account.pkh; _} = Account.new_account () in + let {Account.pkh = delegate_pkh; pk = delegate_pk; _} = + Account.new_account () + in + let contract = Alpha_context.Contract.implicit_contract pkh in + let delegate_contract = + Alpha_context.Contract.implicit_contract delegate_pkh + in + Op.transaction (I i) bootstrap contract (Tez.of_int 10) + >>=? fun op -> + Incremental.add_operation i op + >>=? fun i -> + Op.transaction (I i) bootstrap delegate_contract (Tez.of_int 1) + >>=? fun op -> + Incremental.add_operation i op + >>=? fun i -> + Op.revelation (I i) delegate_pk + >>=? fun op -> + Incremental.add_operation i op + >>=? fun i -> + Op.delegation (I i) delegate_contract (Some delegate_pkh) + >>=? fun op -> + Incremental.add_operation i op + >>=? fun i -> + Op.delegation (I i) contract (Some delegate_pkh) + >>=? fun op -> + Incremental.add_operation i op + >>=? fun i -> + Context.Contract.delegate (I i) contract + >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate delegate_pkh + >>=? fun () -> return_unit + +let tests_delegate_registration = + [ (*** unregistered delegate key: no self-delegation ***) + (* no token transfer, no self-delegation *) + Test_services.tztest + "unregistered delegate key (origination, small fee)" + `Quick + (test_unregistered_delegate_key_init_origination ~fee:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key (origination, edge case fee)" + `Quick + (test_unregistered_delegate_key_init_origination + ~fee:(Tez.of_int 3_999_488)); + Test_services.tztest + "unregistered delegate key (origination, large fee)" + `Quick + (test_unregistered_delegate_key_init_origination + ~fee:(Tez.of_int 10_000_000)); + Test_services.tztest + "unregistered delegate key (init with delegation, small fee)" + `Quick + (test_unregistered_delegate_key_init_delegation ~fee:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key (init with delegation, max fee)" + `Quick + (test_unregistered_delegate_key_init_delegation ~fee:Tez.max_tez); + Test_services.tztest + "unregistered delegate key (switch with delegation, small fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation ~fee:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key (switch with delegation, max fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation ~fee:Tez.max_tez); + (* credit/debit 1μꜩ, no self-delegation *) + Test_services.tztest + "unregistered delegate key - credit/debit 1μꜩ (origination, small fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit_debit + ~fee:Tez.one_mutez + ~amount:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key - credit/debit 1μꜩ (origination, large fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit_debit + ~fee:Tez.max_tez + ~amount:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key - credit/debit 1μꜩ (init with delegation, \ + small fee)" + `Quick + (test_unregistered_delegate_key_init_delegation_credit_debit + ~amount:Tez.one_mutez + ~fee:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key - credit/debit 1μꜩ (init with delegation, \ + large fee)" + `Quick + (test_unregistered_delegate_key_init_delegation_credit_debit + ~amount:Tez.one_mutez + ~fee:Tez.max_tez); + Test_services.tztest + "unregistered delegate key - credit/debit 1μꜩ (switch with \ + delegation, small fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation_credit_debit + ~amount:Tez.one_mutez + ~fee:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key - credit/debit 1μꜩ (switch with \ + delegation, large fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation_credit_debit + ~amount:Tez.one_mutez + ~fee:Tez.max_tez); + (* credit 1μꜩ, no self-delegation *) + Test_services.tztest + "unregistered delegate key - credit 1μꜩ (origination, small fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit + ~fee:Tez.one_mutez + ~amount:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key - credit 1μꜩ (origination, edge case fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit + ~fee:(Tez.of_int 3_999_488) + ~amount:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key - credit 1μꜩ (origination, large fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit + ~fee:(Tez.of_int 10_000_000) + ~amount:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key - credit 1μꜩ (init with delegation, small \ + fee)" + `Quick + (test_unregistered_delegate_key_init_delegation_credit + ~amount:Tez.one_mutez + ~fee:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key - credit 1μꜩ (init with delegation, large \ + fee)" + `Quick + (test_unregistered_delegate_key_init_delegation_credit + ~amount:Tez.one_mutez + ~fee:Tez.max_tez); + Test_services.tztest + "unregistered delegate key - credit 1μꜩ (switch with delegation, \ + small fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation_credit + ~amount:Tez.one_mutez + ~fee:Tez.one_mutez); + Test_services.tztest + "unregistered delegate key - credit 1μꜩ (switch with delegation, \ + large fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation_credit + ~amount:Tez.one_mutez + ~fee:Tez.max_tez); + (* self delegation on unrevealed and unregistered contract *) + Test_services.tztest + "unregistered and unrevealed self-delegation (small fee)" + `Quick + (test_unregistered_and_unrevealed_self_delegate_key_init_delegation + ~fee:Tez.one_mutez); + Test_services.tztest + "unregistered and unrevealed self-delegation (large fee)" + `Quick + (test_unregistered_and_unrevealed_self_delegate_key_init_delegation + ~fee:Tez.max_tez); + (* self delegation on unregistered contract *) + Test_services.tztest + "unregistered and revealed self-delegation (small fee)" + `Quick + (test_unregistered_and_revealed_self_delegate_key_init_delegation + ~fee:Tez.one_mutez); + Test_services.tztest + "unregistered and revealed self-delegation large fee)" + `Quick + (test_unregistered_and_revealed_self_delegate_key_init_delegation + ~fee:Tez.max_tez); + (* self delegation on registered contract *) + Test_services.tztest + "registered and revealed self-delegation" + `Quick + test_registered_self_delegate_key_init_delegation; + (*** unregistered delegate key: failed self-delegation ***) + (* no token transfer, self-delegation *) + Test_services.tztest + "failed self-delegation: no transaction" + `Quick + test_failed_self_delegation_no_transaction; + (* credit 1μtz, debit 1μtz, self-delegation *) + Test_services.tztest + "failed self-delegation: credit & debit 1μꜩ" + `Quick + (test_failed_self_delegation_emptied_implicit_contract Tez.one_mutez); + (* credit 1μtz, delegate, debit 1μtz *) + Test_services.tztest + "empty delegated contract is not deleted: credit 1μꜩ, delegate & \ + debit 1μꜩ" + `Quick + (test_emptying_delegated_implicit_contract_fails Tez.one_mutez); + (*** valid registration ***) + (* valid registration: credit 1 μꜩ, self delegation *) + Test_services.tztest + "valid delegate registration: credit 1μꜩ, self delegation (init with \ + delegation)" + `Quick + (test_valid_delegate_registration_init_delegation_credit Tez.one_mutez); + Test_services.tztest + "valid delegate registration: credit 1μꜩ, self delegation (switch \ + with delegation)" + `Quick + (test_valid_delegate_registration_switch_delegation_credit Tez.one_mutez); + (* valid registration: credit 1 μꜩ, self delegation, debit 1μꜩ *) + Test_services.tztest + "valid delegate registration: credit 1μꜩ, self delegation, debit \ + 1μꜩ (init with delegation)" + `Quick + (test_valid_delegate_registration_init_delegation_credit_debit + Tez.one_mutez); + Test_services.tztest + "valid delegate registration: credit 1μꜩ, self delegation, debit \ + 1μꜩ (switch with delegation)" + `Quick + (test_valid_delegate_registration_switch_delegation_credit_debit + Tez.one_mutez); + (*** double registration ***) + Test_services.tztest "double registration" `Quick test_double_registration; + Test_services.tztest + "double registration when delegate account is emptied" + `Quick + test_double_registration_when_empty; + Test_services.tztest + "double registration when delegate account is emptied and then recredited" + `Quick + test_double_registration_when_recredited ] + +(******************************************************************************) +(* Main *) +(******************************************************************************) + +let tests = tests_bootstrap_contracts @ tests_delegate_registration diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_double_baking.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_double_baking.ml new file mode 100644 index 0000000000000000000000000000000000000000..d9703c4367f2bcaea87db19842a4f40539203880 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_double_baking.ml @@ -0,0 +1,243 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (double baking) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^double baking$" + Subject: Double baking evidence operation may happen when a baker + baked two different blocks on the same level. +*) + +open Protocol +open Alpha_context + +(****************************************************************) +(* Utility functions *) +(****************************************************************) + +let get_hd_hd = function x :: y :: _ -> (x, y) | _ -> assert false + +let get_first_different_baker baker bakers = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun baker' -> Signature.Public_key_hash.( <> ) baker baker') + bakers + +let get_first_different_bakers ctxt = + Context.get_bakers ctxt + >|=? function + | [] | [_] -> + assert false + | baker_1 :: other_bakers -> + (baker_1, get_first_different_baker baker_1 other_bakers) + +let get_first_different_endorsers ctxt = + Context.get_endorsers ctxt >|=? fun endorsers -> get_hd_hd endorsers + +(** Bake two block at the same level using the same policy (i.e. same + baker). *) +let block_fork ?policy contracts b = + let (contract_a, contract_b) = get_hd_hd contracts in + Op.transaction (B b) contract_a contract_b Alpha_context.Tez.one_cent + >>=? fun operation -> + Block.bake ?policy ~operation b + >>=? fun blk_a -> Block.bake ?policy b >|=? fun blk_b -> (blk_a, blk_b) + +(****************************************************************) +(* Tests *) +(****************************************************************) + +(** Simple scenario where two blocks are baked by a same baker and + exposed by a double baking evidence operation. *) +let test_valid_double_baking_evidence () = + Context.init 2 + >>=? fun (b, contracts) -> + Context.get_bakers (B b) + >>=? fun bakers -> + let priority_0_baker = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bakers + in + block_fork ~policy:(By_priority 0) contracts b + >>=? fun (blk_a, blk_b) -> + Op.double_baking (B blk_a) blk_a.header blk_b.header + |> fun operation -> + Block.bake ~policy:(Excluding [priority_0_baker]) ~operation blk_a + >>=? fun blk -> + (* Check that the frozen deposit, the fees and rewards are removed *) + List.iter_es + (fun kind -> + let contract = + Alpha_context.Contract.implicit_contract priority_0_baker + in + Assert.balance_is ~loc:__LOC__ (B blk) contract ~kind Tez.zero) + [Deposit; Fees; Rewards] + +(****************************************************************) +(* The following test scenarios are supposed to raise errors. *) +(****************************************************************) + +(** Check that a double baking operation fails if it exposes the same two + blocks. *) +let test_same_blocks () = + Context.init 2 + >>=? fun (b, _contracts) -> + Block.bake b + >>=? fun ba -> + Op.double_baking (B ba) ba.header ba.header + |> fun operation -> + Block.bake ~operation ba + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Invalid_double_baking_evidence _ -> + true + | _ -> + false) + >>=? fun () -> return_unit + +(** Check that a double baking operation exposing two blocks with + different levels fails. *) +let test_different_levels () = + Context.init 2 + >>=? fun (b, contracts) -> + block_fork ~policy:(By_priority 0) contracts b + >>=? fun (blk_a, blk_b) -> + Block.bake blk_b + >>=? fun blk_b_2 -> + Op.double_baking (B blk_a) blk_a.header blk_b_2.header + |> fun operation -> + Block.bake ~operation blk_a + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Invalid_double_baking_evidence _ -> + true + | _ -> + false) + +(** Check that a double baking operation exposing two yet-to-be-baked + blocks fails. *) +let test_too_early_double_baking_evidence () = + Context.init 2 + >>=? fun (b, contracts) -> + block_fork ~policy:(By_priority 0) contracts b + >>=? fun (blk_a, blk_b) -> + Op.double_baking (B b) blk_a.header blk_b.header + |> fun operation -> + Block.bake ~operation b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Too_early_double_baking_evidence _ -> + true + | _ -> + false) + +(** Check that after [preserved_cycles + 1], it is not possible to + create a double baking operation anymore. *) +let test_too_late_double_baking_evidence () = + Context.init 2 + >>=? fun (b, contracts) -> + Context.get_constants (B b) + >>=? fun Constants.{parametric = {preserved_cycles; _}; _} -> + block_fork ~policy:(By_priority 0) contracts b + >>=? fun (blk_a, blk_b) -> + List.fold_left_es + (fun blk _ -> Block.bake_until_cycle_end blk) + blk_a + (1 -- (preserved_cycles + 1)) + >>=? fun blk -> + Op.double_baking (B blk) blk_a.header blk_b.header + |> fun operation -> + Block.bake ~operation blk + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Outdated_double_baking_evidence _ -> + true + | _ -> + false) + +(** Check that an invalid double baking evidence that exposes two + block baking with same level made by different bakers fails. *) +let test_different_delegates () = + Context.init 2 + >>=? fun (b, _) -> + get_first_different_bakers (B b) + >>=? fun (baker_1, baker_2) -> + Block.bake ~policy:(By_account baker_1) b + >>=? fun blk_a -> + Block.bake ~policy:(By_account baker_2) b + >>=? fun blk_b -> + Op.double_baking (B blk_a) blk_a.header blk_b.header + |> fun operation -> + Block.bake ~operation blk_a + >>= fun e -> + Assert.proto_error ~loc:__LOC__ e (function + | Apply.Inconsistent_double_baking_evidence _ -> + true + | _ -> + false) + +(** Baker_2 bakes a block but baker signs it. *) +let test_wrong_signer () = + let header_custom_signer baker baker_2 b = + Block.Forge.forge_header ~policy:(By_account baker_2) b + >>=? fun header -> + Block.Forge.set_baker baker header |> Block.Forge.sign_header + in + Context.init 2 + >>=? fun (b, _) -> + get_first_different_bakers (B b) + >>=? fun (baker_1, baker_2) -> + Block.bake ~policy:(By_account baker_1) b + >>=? fun blk_a -> + header_custom_signer baker_1 baker_2 b + >>=? fun header_b -> + Op.double_baking (B blk_a) blk_a.header header_b + |> fun operation -> + Block.bake ~operation blk_a + >>= fun e -> + Assert.proto_error ~loc:__LOC__ e (function + | Baking.Invalid_block_signature _ -> + true + | _ -> + false) + +let tests = + [ Test_services.tztest + "valid double baking evidence" + `Quick + test_valid_double_baking_evidence; + (* Should fail*) + Test_services.tztest "same blocks" `Quick test_same_blocks; + Test_services.tztest "different levels" `Quick test_different_levels; + Test_services.tztest + "too early double baking evidence" + `Quick + test_too_early_double_baking_evidence; + Test_services.tztest + "too late double baking evidence" + `Quick + test_too_late_double_baking_evidence; + Test_services.tztest "different delegates" `Quick test_different_delegates; + Test_services.tztest "wrong delegate" `Quick test_wrong_signer ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_double_endorsement.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_double_endorsement.ml new file mode 100644 index 0000000000000000000000000000000000000000..e4f6703b86fb6e4cf3abfd5d6504ac4af7b055dd --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_double_endorsement.ml @@ -0,0 +1,293 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (double endorsement) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^double endorsement$" + Subject: Double endorsement evidence operation may happen when an + endorser endorsed two different blocks on the same level. +*) + +open Protocol +open Alpha_context + +(****************************************************************) +(* Utility functions *) +(****************************************************************) + +let get_hd_hd = function x :: y :: _ -> (x, y) | _ -> assert false + +let get_first_different_baker baker bakers = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun baker' -> Signature.Public_key_hash.( <> ) baker baker') + bakers + +let get_first_different_bakers ctxt = + Context.get_bakers ctxt + >|=? function + | [] -> + assert false + | baker_1 :: other_bakers -> + (baker_1, get_first_different_baker baker_1 other_bakers) + +let get_first_different_endorsers ctxt = + Context.get_endorsers ctxt >|=? fun endorsers -> get_hd_hd endorsers + +let block_fork b = + get_first_different_bakers (B b) + >>=? fun (baker_1, baker_2) -> + Block.bake ~policy:(By_account baker_1) b + >>=? fun blk_a -> + Block.bake ~policy:(By_account baker_2) b >|=? fun blk_b -> (blk_a, blk_b) + +(****************************************************************) +(* Tests *) +(****************************************************************) + +(** Simple scenario where two endorsements are made from the same + delegate and exposed by a double_endorsement operation. Also verify + that punishment is operated. *) +let test_valid_double_endorsement_evidence () = + Context.init 2 + >>=? fun (b, _) -> + block_fork b + >>=? fun (blk_a, blk_b) -> + Context.get_endorser (B blk_a) + >>=? fun (delegate, slots) -> + Op.endorsement ~delegate (B blk_a) () + >>=? fun endorsement_a -> + Op.endorsement ~delegate (B blk_b) () + >>=? fun endorsement_b -> + Op.endorsement_with_slot ~delegate:(delegate, slots) (B blk_a) () + >>=? fun endorsement_with_slot_a -> + Block.bake ~operations:[Operation.pack endorsement_with_slot_a] blk_a + >>=? fun blk_a -> + (* Block.bake ~operations:[endorsement_b] blk_b >>=? fun _ -> *) + Op.double_endorsement + (B blk_a) + endorsement_a + endorsement_b + ~slot:(WithExceptions.Option.get ~loc:__LOC__ (List.hd slots)) + |> fun operation -> + (* Bake with someone different than the bad endorser *) + Context.get_bakers (B blk_a) + >>=? fun bakers -> + get_first_different_baker delegate bakers + |> fun baker -> + Block.bake ~policy:(By_account baker) ~operation blk_a + >>=? fun blk -> + (* Check that the frozen deposit, the fees and rewards are removed *) + List.iter_es + (fun kind -> + let contract = Alpha_context.Contract.implicit_contract delegate in + Assert.balance_is ~loc:__LOC__ (B blk) contract ~kind Tez.zero) + [Deposit; Fees; Rewards] + +(****************************************************************) +(* The following test scenarios are supposed to raise errors. *) +(****************************************************************) + +(** Check that an invalid double endorsement operation that exposes a + valid endorsement fails. *) +let test_invalid_double_endorsement () = + Context.init 10 + >>=? fun (b, _) -> + Block.bake b + >>=? fun b -> + Op.endorsement (B b) () + >>=? fun endorsement -> + Op.endorsement_with_slot (B b) () + >>=? fun endorsement_with_slot -> + Block.bake ~operation:(Operation.pack endorsement_with_slot) b + >>=? fun b -> + Op.double_endorsement (B b) endorsement endorsement ~slot:0 + |> fun operation -> + Block.bake ~operation b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Invalid_double_endorsement_evidence -> + true + | _ -> + false) + +(** Check that a double endorsement added at the same time as a double + endorsement operation fails. *) +let test_too_early_double_endorsement_evidence () = + Context.init 2 + >>=? fun (b, _) -> + block_fork b + >>=? fun (blk_a, blk_b) -> + Context.get_endorser (B blk_a) + >>=? fun (delegate, slots) -> + Op.endorsement ~delegate (B blk_a) () + >>=? fun endorsement_a -> + Op.endorsement ~delegate (B blk_b) () + >>=? fun endorsement_b -> + Op.double_endorsement + (B b) + endorsement_a + endorsement_b + ~slot:(WithExceptions.Option.get ~loc:__LOC__ (List.hd slots)) + |> fun operation -> + Block.bake ~operation b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Too_early_double_endorsement_evidence _ -> + true + | _ -> + false) + +(** Check that after [preserved_cycles + 1], it is not possible + to create a double_endorsement anymore. *) +let test_too_late_double_endorsement_evidence () = + Context.init 2 + >>=? fun (b, _) -> + Context.get_constants (B b) + >>=? fun Constants.{parametric = {preserved_cycles; _}; _} -> + block_fork b + >>=? fun (blk_a, blk_b) -> + Context.get_endorser (B blk_a) + >>=? fun (delegate, slots) -> + Op.endorsement ~delegate (B blk_a) () + >>=? fun endorsement_a -> + Op.endorsement ~delegate (B blk_b) () + >>=? fun endorsement_b -> + List.fold_left_es + (fun blk _ -> Block.bake_until_cycle_end blk) + blk_a + (1 -- (preserved_cycles + 1)) + >>=? fun blk -> + Op.double_endorsement + (B blk) + endorsement_a + endorsement_b + ~slot:(WithExceptions.Option.get ~loc:__LOC__ (List.hd slots)) + |> fun operation -> + Block.bake ~operation blk + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Outdated_double_endorsement_evidence _ -> + true + | _ -> + false) + +(** Check that an invalid double endorsement evidence that exposes two + endorsements made by two different endorsers fails. *) +let test_different_delegates () = + Context.init 2 + >>=? fun (b, _) -> + Block.bake b + >>=? fun b -> + block_fork b + >>=? fun (blk_a, blk_b) -> + Context.get_endorser (B blk_a) + >>=? fun (endorser_a, _a_slots) -> + get_first_different_endorsers (B blk_b) + >>=? fun (endorser_b1c, endorser_b2c) -> + let (endorser_b, b_slots) = + if Signature.Public_key_hash.( = ) endorser_a endorser_b1c.delegate then + (endorser_b2c.delegate, endorser_b2c.slots) + else (endorser_b1c.delegate, endorser_b1c.slots) + in + Op.endorsement ~delegate:endorser_a (B blk_a) () + >>=? fun e_a -> + Op.endorsement ~delegate:endorser_b (B blk_b) () + >>=? fun e_b -> + Op.endorsement_with_slot ~delegate:(endorser_b, b_slots) (B blk_b) () + >>=? fun e_ws_b -> + Block.bake ~operation:(Operation.pack e_ws_b) blk_b + >>=? fun _ -> + Op.double_endorsement + (B blk_b) + e_a + e_b + ~slot:(WithExceptions.Option.get ~loc:__LOC__ (List.hd b_slots)) + |> fun operation -> + Block.bake ~operation blk_b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Baking.Unexpected_endorsement -> + true + | _ -> + false) + +(** Check that a double endorsement evidence that exposes a ill-formed + endorsement fails. *) +let test_wrong_delegate () = + Context.init ~endorsers_per_block:1 2 + >>=? fun (b, contracts) -> + List.map_es (Context.Contract.manager (B b)) contracts + >>=? fun accounts -> + let (account_1, account_2) = get_hd_hd accounts in + let pkh1 = account_1.Account.pkh in + let pkh2 = account_2.Account.pkh in + block_fork b + >>=? fun (blk_a, blk_b) -> + Context.get_endorser (B blk_a) + >>=? fun (endorser_a, a_slots) -> + Op.endorsement ~delegate:endorser_a (B blk_a) () + >>=? fun endorsement_a -> + Context.get_endorser (B blk_b) + >>=? fun (endorser_b, _b_slots) -> + let delegate = + if Signature.Public_key_hash.equal pkh1 endorser_b then pkh2 else pkh1 + in + Op.endorsement ~delegate (B blk_b) () + >>=? fun endorsement_b -> + Op.double_endorsement + (B blk_b) + endorsement_a + endorsement_b + ~slot:(WithExceptions.Option.get ~loc:__LOC__ (List.hd a_slots)) + |> fun operation -> + Block.bake ~operation blk_b + >>= fun e -> + Assert.proto_error ~loc:__LOC__ e (function + | Baking.Unexpected_endorsement -> + true + | _ -> + false) + +let tests = + [ Test_services.tztest + "valid double endorsement evidence" + `Quick + test_valid_double_endorsement_evidence; + Test_services.tztest + "invalid double endorsement evidence" + `Quick + test_invalid_double_endorsement; + Test_services.tztest + "too early double endorsement evidence" + `Quick + test_too_early_double_endorsement_evidence; + Test_services.tztest + "too late double endorsement evidence" + `Quick + test_too_late_double_endorsement_evidence; + Test_services.tztest "different delegates" `Quick test_different_delegates; + Test_services.tztest "wrong delegate" `Quick test_wrong_delegate ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_endorsement.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_endorsement.ml new file mode 100644 index 0000000000000000000000000000000000000000..4a7c3b1e63180027d22dc26939434b03f17a3fb5 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_endorsement.ml @@ -0,0 +1,785 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (endorsement) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^endorsement$" + Subject: Endorsing a block adds an extra layer of confidence to the + Tezos' PoS algorithm. The block endorsing operation must be + included in the following block. Each endorser possesses a + number of slots corresponding to their priority. After + [preserved_cycles], a reward is given to the endorser. This + reward depends on the priority of the block that contains + the endorsements. +*) + +open Protocol +open Alpha_context +open Test_tez + +(****************************************************************) +(* Utility functions *) +(****************************************************************) + +let get_hd_hd = function x :: y :: _ -> (x, y) | _ -> assert false + +let get_expected_reward ctxt ~priority ~baker ~endorsing_power = + ( if baker then Context.get_baking_reward ctxt ~priority ~endorsing_power + else return (Test_tez.Tez.of_int 0) ) + >>=? fun baking_reward -> + Context.get_endorsing_reward ctxt ~priority ~endorsing_power + >>=? fun endorsing_reward -> + Test_tez.Tez.(endorsing_reward +? baking_reward) + >>?= fun reward -> return reward + +let get_expected_deposit ctxt ~baker ~endorsing_power = + Context.get_constants ctxt + >>=? fun Constants. + { parametric = + {endorsement_security_deposit; block_security_deposit; _}; + _ } -> + let open Environment in + let open Tez in + let baking_deposit = if baker then block_security_deposit else of_int 0 in + endorsement_security_deposit *? Int64.of_int endorsing_power + >>?= fun endorsement_deposit -> + endorsement_deposit +? baking_deposit >>?= fun deposit -> return deposit + +(* [baker] is true if the [pkh] has also baked the current block, in + which case corresponding deposit and reward should be adjusted *) +let assert_endorser_balance_consistency ~loc ?(priority = 0) ?(baker = false) + ~endorsing_power ctxt pkh initial_balance = + let contract = Contract.implicit_contract pkh in + get_expected_reward ctxt ~priority ~baker ~endorsing_power + >>=? fun reward -> + get_expected_deposit ctxt ~baker ~endorsing_power + >>=? fun deposit -> + Assert.balance_was_debited ~loc ctxt contract initial_balance deposit + >>=? fun () -> + Context.Contract.balance ~kind:Rewards ctxt contract + >>=? fun reward_balance -> + Assert.equal_tez ~loc reward_balance reward + >>=? fun () -> + Context.Contract.balance ~kind:Deposit ctxt contract + >>=? fun deposit_balance -> Assert.equal_tez ~loc deposit_balance deposit + +let delegates_with_slots endorsers = + List.map + (fun (endorser : Delegate_services.Endorsing_rights.t) -> + (endorser.delegate, endorser.slots)) + endorsers + +let endorsing_power endorsers = + List.fold_left + (fun sum (endorser : Delegate_services.Endorsing_rights.t) -> + sum + List.length endorser.slots) + 0 + endorsers + +(****************************************************************) +(* Tests *) +(****************************************************************) + +(** Apply a single endorsement from the slot 0 endorser. *) +let test_simple_endorsement () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_endorser (B b) + >>=? fun (delegate, slots) -> + Op.endorsement_with_slot ~delegate:(delegate, slots) (B b) () + >>=? fun op -> + Context.Contract.balance (B b) (Contract.implicit_contract delegate) + >>=? fun initial_balance -> + let policy = Block.Excluding [delegate] in + Block.get_next_baker ~policy b + >>=? fun (_, priority, _) -> + Block.bake ~policy ~operations:[Operation.pack op] b + >>=? fun b2 -> + assert_endorser_balance_consistency + ~loc:__LOC__ + (B b2) + ~priority + ~endorsing_power:(List.length slots) + delegate + initial_balance + +(** Apply a maximum number of endorsements. An endorser can be + selected twice. *) +let test_max_endorsement () = + let endorsers_per_block = 16 in + Context.init ~endorsers_per_block 32 + >>=? fun (b, _) -> + Context.get_endorsers (B b) + >>=? fun endorsers -> + Assert.equal_int + ~loc:__LOC__ + (List.length + (List.concat + (List.map + (fun {Alpha_services.Delegate.Endorsing_rights.slots; _} -> slots) + endorsers))) + endorsers_per_block + >>=? fun () -> + List.fold_left_es + (fun (delegates, ops, balances) + (endorser : Alpha_services.Delegate.Endorsing_rights.t) -> + let delegate = endorser.delegate in + Context.Contract.balance (B b) (Contract.implicit_contract delegate) + >>=? fun balance -> + Op.endorsement_with_slot ~delegate:(delegate, endorser.slots) (B b) () + >|=? fun op -> + ( delegate :: delegates, + Operation.pack op :: ops, + (List.length endorser.slots, balance) :: balances )) + ([], [], []) + endorsers + >>=? fun (delegates, ops, previous_balances) -> + Block.bake ~policy:(Excluding delegates) ~operations:(List.rev ops) b + >>=? fun b -> + (* One account can endorse more than one time per level, we must + check that the bonds are summed up *) + List.iter2_es + ~when_different_lengths:(TzTrace.make (Exn (Failure __LOC__))) + (fun endorser_account (endorsing_power, previous_balance) -> + assert_endorser_balance_consistency + ~loc:__LOC__ + (B b) + ~endorsing_power + endorser_account + previous_balance) + delegates + previous_balances + +(** Check that every endorsers' balances are consistent with different + priorities. *) +let test_consistent_priorities () = + let priorities = 0 -- 64 in + Context.init 64 + >>=? fun (b, _) -> + List.fold_left_es + (fun (b, used_pkhes) priority -> + (* Choose an endorser that has not baked nor endorsed before *) + Context.get_endorsers (B b) + >>=? fun endorsers -> + let endorser = + List.find_opt + (fun (e : Delegate_services.Endorsing_rights.t) -> + not (Signature.Public_key_hash.Set.mem e.delegate used_pkhes)) + endorsers + in + match endorser with + | None -> + return (b, used_pkhes) (* not enough fresh endorsers; we "stop" *) + | Some endorser -> + Context.Contract.balance + (B b) + (Contract.implicit_contract endorser.delegate) + >>=? fun balance -> + Op.endorsement_with_slot + ~delegate:(endorser.delegate, endorser.slots) + (B b) + () + >>=? fun operation -> + let operation = Operation.pack operation in + Block.get_next_baker ~policy:(By_priority priority) b + >>=? fun (baker, _, _) -> + let used_pkhes = + Signature.Public_key_hash.Set.add baker used_pkhes + in + let used_pkhes = + Signature.Public_key_hash.Set.add endorser.delegate used_pkhes + in + (* Bake with a specific priority *) + Block.bake ~policy:(By_priority priority) ~operation b + >>=? fun b -> + let is_baker = + Signature.Public_key_hash.(baker = endorser.delegate) + in + assert_endorser_balance_consistency + ~loc:__LOC__ + ~priority + ~baker:is_baker + (B b) + ~endorsing_power:(List.length endorser.slots) + endorser.delegate + balance + >|=? fun () -> (b, used_pkhes)) + (b, Signature.Public_key_hash.Set.empty) + priorities + >>=? fun _b -> return_unit + +(** Check that after [preserved_cycles] number of cycles the endorser + gets his reward. *) +let test_reward_retrieval () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_constants (B b) + >>=? fun Constants.{parametric = {preserved_cycles; _}; _} -> + Context.get_endorser (B b) + >>=? fun (endorser, slots) -> + Context.Contract.balance (B b) (Contract.implicit_contract endorser) + >>=? fun balance -> + Op.endorsement_with_slot ~delegate:(endorser, slots) (B b) () + >>=? fun operation -> + let operation = Operation.pack operation in + let policy = Block.Excluding [endorser] in + Block.get_next_baker ~policy b + >>=? fun (_, priority, _) -> + Block.bake ~policy ~operation b + >>=? fun b -> + (* Bake (preserved_cycles + 1) cycles *) + List.fold_left_es + (fun b _ -> Block.bake_until_cycle_end ~policy:(Excluding [endorser]) b) + b + (0 -- preserved_cycles) + >>=? fun b -> + get_expected_reward + (B b) + ~priority + ~baker:false + ~endorsing_power:(List.length slots) + >>=? fun reward -> + Assert.balance_was_credited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser) + balance + reward + +(** Check that after [preserved_cycles] number of cycles endorsers get + their reward. Two endorsers are used and they endorse in different + cycles. *) +let test_reward_retrieval_two_endorsers () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_constants (B b) + >>=? fun Constants. + { parametric = {preserved_cycles; endorsement_security_deposit; _}; + _ } -> + Context.get_endorsers (B b) + >>=? fun endorsers -> + let (endorser1, endorser2) = get_hd_hd endorsers in + Context.Contract.balance + (B b) + (Contract.implicit_contract endorser1.delegate) + >>=? fun balance1 -> + Context.Contract.balance + (B b) + (Contract.implicit_contract endorser2.delegate) + >>=? fun balance2 -> + Tez.( + endorsement_security_deposit *? Int64.of_int (List.length endorser1.slots)) + >>?= fun security_deposit1 -> + (* endorser1 endorses the genesis block in cycle 0 *) + Op.endorsement_with_slot + ~delegate:(endorser1.delegate, endorser1.slots) + (B b) + () + >>=? fun operation1 -> + let policy = Block.Excluding [endorser1.delegate; endorser2.delegate] in + Block.get_next_baker ~policy b + >>=? fun (_, priority, _) -> + Context.get_endorsing_reward + (B b) + ~priority + ~endorsing_power:(List.length endorser1.slots) + >>=? fun reward1 -> + (* bake next block, include endorsement of endorser1 *) + Block.bake ~policy ~operation:(Operation.pack operation1) b + >>=? fun b -> + Assert.balance_was_debited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser1.delegate) + balance1 + security_deposit1 + >>=? fun () -> + Assert.balance_is + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser2.delegate) + balance2 + >>=? fun () -> + (* complete cycle 0 *) + Block.bake_until_cycle_end ~policy b + >>=? fun b -> + Assert.balance_was_debited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser1.delegate) + balance1 + security_deposit1 + >>=? fun () -> + Assert.balance_is + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser2.delegate) + balance2 + >>=? fun () -> + (* get the slots of endorser2 for the current block *) + Context.get_endorsers (B b) + >>=? fun endorsers -> + let same_endorser2 endorser = + Signature.Public_key_hash.( + endorser.Delegate_services.Endorsing_rights.delegate = endorser2.delegate) + in + let endorser2 = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find same_endorser2 endorsers + in + (* No exception raised: in sandboxed mode endorsers do not change between blocks *) + Tez.( + endorsement_security_deposit *? Int64.of_int (List.length endorser2.slots)) + >>?= fun security_deposit2 -> + (* endorser2 endorses the last block in cycle 0 *) + Op.endorsement_with_slot + ~delegate:(endorser2.delegate, endorser2.slots) + (B b) + () + >>=? fun operation2 -> + (* bake first block in cycle 1, include endorsement of endorser2 *) + Block.bake ~policy ~operation:(Operation.pack operation2) b + >>=? fun b -> + let priority = b.header.protocol_data.contents.priority in + Context.get_endorsing_reward + (B b) + ~priority + ~endorsing_power:(List.length endorser2.slots) + >>=? fun reward2 -> + Assert.balance_was_debited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser1.delegate) + balance1 + security_deposit1 + >>=? fun () -> + Assert.balance_was_debited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser2.delegate) + balance2 + security_deposit2 + >>=? fun () -> + (* bake [preserved_cycles] number of cycles *) + List.fold_left_es + (fun b _ -> + Assert.balance_was_debited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser1.delegate) + balance1 + security_deposit1 + >>=? fun () -> + Assert.balance_was_debited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser2.delegate) + balance2 + security_deposit2 + >>=? fun () -> Block.bake_until_cycle_end ~policy b) + b + (1 -- preserved_cycles) + >>=? fun b -> + Assert.balance_was_credited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser1.delegate) + balance1 + reward1 + >>=? fun () -> + Assert.balance_was_debited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser2.delegate) + balance2 + security_deposit2 + >>=? fun () -> + (* bake cycle [preserved_cycle + 1] *) + Block.bake_until_cycle_end ~policy b + >>=? fun b -> + Assert.balance_was_credited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser1.delegate) + balance1 + reward1 + >>=? fun () -> + Assert.balance_was_credited + ~loc:__LOC__ + (B b) + (Contract.implicit_contract endorser2.delegate) + balance2 + reward2 + +(****************************************************************) +(* The following test scenarios are supposed to raise errors. *) +(****************************************************************) + +(** Apply an endorsement without its slot bearing wrapper. *) +let test_unwrapped_endorsement () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_endorser (B b) + >>=? fun (delegate, _slots) -> + Op.endorsement ~delegate (B b) () + >>=? fun op -> + let policy = Block.Excluding [delegate] in + Block.bake ~policy ~operations:[Operation.pack op] b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Unwrapped_endorsement -> + true + | _ -> + false) + +(** Apply an endorsement with an invalid slot in its slot bearing wrapper. *) +let test_bad_slot_wrapper () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_endorser (B b) + >>=? fun (delegate, _slots) -> + Op.endorsement_with_slot ~delegate:(delegate, [2000]) (B b) () + >>=? fun op -> + let policy = Block.Excluding [delegate] in + Block.bake ~policy ~operations:[Operation.pack op] b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Baking.Invalid_endorsement_slot _ -> + true + | _ -> + false) + +(** Apply an endorsement with a negative slot in its slot bearing wrapper. *) +let test_neg_slot_wrapper () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_endorser (B b) + >>=? fun (delegate, _slots) -> + Op.endorsement_with_slot ~delegate:(delegate, [-1]) (B b) () + >>=? fun op -> + let policy = Block.Excluding [delegate] in + Lwt.catch + (fun () -> + Block.bake ~policy ~operations:[Operation.pack op] b + >>= fun _ -> + failwith + "negative slot wrapper should not be accepted by the binary format") + (function + | Data_encoding.Binary.Write_error _ -> return_unit | e -> Lwt.fail e) + +(** Apply an endorsement with a non-normalized slot in its slot bearing wrapper. *) +let test_non_normalized_slot_wrapper () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_endorsers (B b) + >>=? fun endorsers -> + (* find an endorsers with more than 1 slot *) + let endorser = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun endorser -> + List.length endorser.Delegate_services.Endorsing_rights.slots > 1) + endorsers + in + let (delegate, slots) = (endorser.delegate, endorser.slots) in + (* the first slot should be the smallest slot *) + Assert.equal_int + ~loc:__LOC__ + (WithExceptions.Option.get ~loc:__LOC__ @@ List.hd endorser.slots) + ( WithExceptions.Option.get ~loc:__LOC__ + @@ List.hd (List.sort compare endorser.slots) ) + >>=? fun () -> + Op.endorsement_with_slot ~delegate:(delegate, List.rev slots) (B b) () + >>=? fun op -> + let policy = Block.Excluding [delegate] in + Block.bake ~policy ~operations:[Operation.pack op] b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Baking.Unexpected_endorsement_slot _ -> + true + | _ -> + false) + +(** Wrong endorsement predecessor : apply an endorsement with an + incorrect block predecessor. *) +let test_wrong_endorsement_predecessor () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_endorser (B b) + >>=? fun (genesis_endorser, slots) -> + Block.bake b + >>=? fun b' -> + Op.endorsement_with_slot + ~delegate:(genesis_endorser, slots) + ~signing_context:(B b) + (B b') + () + >>=? fun operation -> + let operation = Operation.pack operation in + Block.bake ~operation b' + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Wrong_endorsement_predecessor _ -> + true + | _ -> + false) + +(** Invalid_endorsement_level: apply an endorsement with an incorrect + level (i.e. the predecessor level). *) +let test_invalid_endorsement_level () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_level (B b) + >>?= fun genesis_level -> + Block.bake b + >>=? fun b -> + Op.endorsement_with_slot ~level:genesis_level (B b) () + >>=? fun operation -> + let operation = Operation.pack operation in + Block.bake ~operation b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Invalid_endorsement_level -> + true + | _ -> + false) + +(** Duplicate endorsement : apply an endorsement that has already been + done. *) +let test_duplicate_endorsement () = + Context.init 5 + >>=? fun (b, _) -> + Incremental.begin_construction b + >>=? fun inc -> + Op.endorsement_with_slot (B b) () + >>=? fun operation -> + let operation = Operation.pack operation in + Incremental.add_operation inc operation + >>=? fun inc -> + Op.endorsement_with_slot (B b) () + >>=? fun operation -> + let operation = Operation.pack operation in + Incremental.add_operation inc operation + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Duplicate_endorsement _ -> + true + | _ -> + false) + +(** Apply a single endorsement from the slot 0 endorser. *) +let test_not_enough_for_deposit () = + Context.init 5 ~endorsers_per_block:1 + >>=? fun (b_init, contracts) -> + List.map_es + (fun c -> Context.Contract.manager (B b_init) c >|=? fun m -> (m, c)) + contracts + >>=? fun managers -> + Block.bake b_init + >>=? fun b -> + (* retrieve the level 2's endorser *) + Context.get_endorser (B b) + >>=? fun (endorser, slots) -> + let (_, contract_other_than_endorser) = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun (c, _) -> + not (Signature.Public_key_hash.equal c.Account.pkh endorser)) + managers + in + let (_, contract_of_endorser) = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun (c, _) -> Signature.Public_key_hash.equal c.Account.pkh endorser) + managers + in + Context.Contract.balance (B b) (Contract.implicit_contract endorser) + >>=? fun initial_balance -> + (* Empty the future endorser account *) + Op.transaction + (B b_init) + contract_of_endorser + contract_other_than_endorser + initial_balance + >>=? fun op_trans -> + Block.bake ~operation:op_trans b_init + >>=? fun b -> + (* Endorse with a zero balance *) + Op.endorsement_with_slot ~delegate:(endorser, slots) (B b) () + >>=? fun op_endo -> + Block.bake + ~policy:(Excluding [endorser]) + ~operation:(Operation.pack op_endo) + b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Delegate_storage.Balance_too_low_for_deposit _ -> + true + | _ -> + false) + +(** Check that a block with not enough endorsement cannot be baked. *) +let test_endorsement_threshold () = + let initial_endorsers = 28 in + let num_accounts = 100 in + Context.init ~initial_endorsers num_accounts + >>=? fun (b, _) -> + Context.get_endorsers (B b) + >>=? fun endorsers -> + let num_endorsers = List.length endorsers in + (* we try to bake with more and more endorsers, but at each + iteration with a timestamp smaller than required *) + List.iter_es + (fun i -> + (* the priority is chosen rather arbitrarily *) + let priority = num_endorsers - i in + let crt_endorsers = List.take_n i endorsers in + let endorsing_power = endorsing_power crt_endorsers in + let delegates = delegates_with_slots crt_endorsers in + List.map_es + (fun x -> Op.endorsement_with_slot ~delegate:x (B b) ()) + delegates + >>=? fun ops -> + Context.get_minimal_valid_time (B b) ~priority ~endorsing_power + >>=? fun timestamp -> + (* decrease the timestamp by one second *) + let seconds = + Int64.(sub (of_string (Timestamp.to_seconds_string timestamp)) 1L) + in + match Timestamp.of_seconds_string (Int64.to_string seconds) with + | None -> + failwith "timestamp to/from string manipulation failed" + | Some timestamp -> + Block.bake + ~timestamp + ~policy:(By_priority priority) + ~operations:(List.map Operation.pack ops) + b + >>= fun b2 -> + Assert.proto_error ~loc:__LOC__ b2 (function + | Baking.Timestamp_too_early _ + | Apply.Not_enough_endorsements_for_priority _ -> + true + | _ -> + false)) + (0 -- (num_endorsers - 1)) + >>=? fun () -> + (* we bake with all endorsers endorsing, at the right time *) + let priority = 0 in + let endorsing_power = endorsing_power endorsers in + let delegates = delegates_with_slots endorsers in + List.map_es + (fun delegate -> Op.endorsement_with_slot ~delegate (B b) ()) + delegates + >>=? fun ops -> + Context.get_minimal_valid_time (B b) ~priority ~endorsing_power + >>=? fun timestamp -> + Block.bake + ~policy:(By_priority priority) + ~timestamp + ~operations:(List.map Operation.pack ops) + b + >>= fun _ -> return_unit + +(** Fitness gap *) +let test_fitness_gap () = + let num_accounts = 5 in + Context.init num_accounts + >>=? fun (b, _) -> + ( match Fitness_repr.to_int64 b.header.shell.fitness with + | Ok fitness -> + Int64.to_int fitness + | Error _ -> + assert false ) + |> fun fitness -> + Context.get_endorser (B b) + >>=? fun (delegate, slots) -> + Op.endorsement_with_slot ~delegate:(delegate, slots) (B b) () + >>=? fun op -> + (* bake at priority 0 succeed thanks to enough endorsements *) + Block.bake ~policy:(By_priority 0) ~operations:[Operation.pack op] b + >>=? fun b -> + ( match Fitness_repr.to_int64 b.header.shell.fitness with + | Ok new_fitness -> + Int64.to_int new_fitness - fitness + | Error _ -> + assert false ) + |> fun res -> + (* in Emmy+, the fitness increases by 1, so the difference between + the fitness at level 1 and at level 0 is 1, independently if the + number fo endorsements (here 1) *) + Assert.equal_int ~loc:__LOC__ res 1 >>=? fun () -> return_unit + +let tests = + [ Test_services.tztest "Simple endorsement" `Quick test_simple_endorsement; + Test_services.tztest + "Unwrapped endorsement" + `Quick + test_unwrapped_endorsement; + Test_services.tztest + "Endorsement wrapped with invalid slot" + `Quick + test_bad_slot_wrapper; + Test_services.tztest + "Endorsement wrapped with slot -1" + `Quick + test_neg_slot_wrapper; + Test_services.tztest + "Endorsement wrapped with non-normalized slot" + `Quick + test_non_normalized_slot_wrapper; + Test_services.tztest "Maximum endorsement" `Quick test_max_endorsement; + Test_services.tztest + "Consistent priorities" + `Quick + test_consistent_priorities; + Test_services.tztest "Reward retrieval" `Quick test_reward_retrieval; + Test_services.tztest + "Reward retrieval two endorsers" + `Quick + test_reward_retrieval_two_endorsers; + Test_services.tztest + "Endorsement threshold" + `Quick + test_endorsement_threshold; + Test_services.tztest "Fitness gap" `Quick test_fitness_gap; + (* Fail scenarios *) + Test_services.tztest + "Wrong endorsement predecessor" + `Quick + test_wrong_endorsement_predecessor; + Test_services.tztest + "Invalid endorsement level" + `Quick + test_invalid_endorsement_level; + Test_services.tztest + "Duplicate endorsement" + `Quick + test_duplicate_endorsement; + Test_services.tztest + "Not enough for deposit" + `Quick + test_not_enough_for_deposit ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_failing_noop.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_failing_noop.ml new file mode 100644 index 0000000000000000000000000000000000000000..268538db4f81caac7b5b209b36265780348795d6 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_failing_noop.ml @@ -0,0 +1,73 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe\ + -- test "^failing_noop$" + Subject: The Failing_noop operation was added bearing in mind the + possibility for the end user to sign arbitrary bytes, + encapsulate in the operation, with the absolute garanty that + the signed bytes can't be used for something against the + user's will. The Failing_noop operation always fails when + applied. + *) + +open Protocol +open Alpha_context + +let register_one_contract () = + Context.init 1 + >>=? fun (b, contracts) -> + let contract = + List.nth contracts 0 |> WithExceptions.Option.get ~loc:__LOC__ + in + return (b, contract) + +(** try to apply a failing_noop and assert that the operation fails *) +let failing_noop_must_fail_when_injected () = + register_one_contract () + >>=? fun (blk, contract) -> + Contract.is_implicit contract + |> function + | None -> + Alcotest.fail "only implicit accounts can sign" + | Some source -> + Op.failing_noop (B blk) source "tezos" + >>=? fun operation -> + Block.bake ~operation blk + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Apply.Failing_noop_error -> + true + | _ -> + false) + +let tests = + [ Test_services.tztest + "injection fails" + `Quick + failing_noop_must_fail_when_injected ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_fixed_point.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_fixed_point.ml new file mode 100644 index 0000000000000000000000000000000000000000..689b201315aec1c6fee2eda9764f3a0c2d035efb --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_fixed_point.ml @@ -0,0 +1,175 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (fixed-point decimals) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^fixed point computation$" + Subject: On fixed-point decimal numbers. +*) + +open Protocol + +exception Fixed_point_test_error of string + +let err x = Exn (Fixed_point_test_error x) + +module type Arith = sig + type t + + val zero : t + + val equal : t -> t -> bool + + val random : unit -> t + + val add : t -> t -> t + + val sub : t -> t -> t +end + +let n = Z.of_int 42 + +let n' = Z.of_int 43 + +let basic_arith name (module A : Arith) = + let err msg = err (Format.asprintf "%s test: %s" name msg) in + let x = A.random () in + fail_unless A.(add zero x = x) (err "zero is neutral for +") + >>=? fun () -> + let x = A.random () in + let y = A.random () in + fail_unless A.(add x y = add y x) (err "addition is commutative") + >>=? fun () -> + let x = A.random () in + fail_unless + A.(sub (add zero x) x = zero) + (err "addition and subtraction cancel") + >>=? fun () -> + let x = A.random () in + let y = A.random () in + let z = A.random () in + fail_unless + A.(add x (add y z) = add (add x y) z) + (err "addition is associative") + +let arith_from_integral : (module Fixed_point_repr.Full) -> (module Arith) = + fun (module FP) -> + let module Arith = struct + type t = FP.integral + + let zero = FP.zero + + let equal = FP.equal + + let random () = FP.integral_of_int_exn (Random.int 898987) + + let add = FP.add + + let sub = FP.sub + end in + (module Arith) + +let arith_from_fp : (module Fixed_point_repr.Full) -> (module Arith) = + fun (module FP) -> + let module Arith = struct + type t = FP.fp + + let zero = FP.zero + + let equal = FP.equal + + let random () = FP.unsafe_fp (Z.of_int (Random.int 898987)) + + let add = FP.add + + let sub = FP.sub + end in + (module Arith) + +let integral_tests () = + let module FP = Gas_limit_repr.Arith in + (* test roundtrips *) + fail_unless (FP.(integral_to_z (integral_exn n)) = n) (err "roundtrip > 0") + >>=? fun () -> + fail_unless + (FP.(integral_to_z (integral_exn Z.zero)) = Z.zero) + (err "roundtrip = 0") + >>=? fun () -> + (* test ceil/floor on integral *) + fail_unless + FP.(ceil (fp (integral_exn n)) = integral_exn n) + (err "integral;fp;ceil = integral") + >>=? fun () -> + fail_unless + FP.(floor (fp (integral_exn n)) = integral_exn n) + (err "integral;fp;floor = integral") + >>=? fun () -> + fail_unless + ( Format.asprintf "%a" FP.pp FP.(fp (integral_exn n)) + = Format.asprintf "%a" FP.pp_integral (FP.integral_exn n) ) + (err "pp_integral(integral) = pp(fp(integral))") + >>=? fun () -> basic_arith "integral arith" (arith_from_integral (module FP)) + +let fp_nonzero () = + let decimals = 3 in + let module FP = Gas_limit_repr.Arith in + let prefix msg = Format.asprintf "(%d decimals) %s" decimals msg in + let err msg = err (prefix msg) in + basic_arith (prefix "integral arith") (arith_from_integral (module FP)) + >>=? fun () -> + basic_arith (prefix "fp arith") (arith_from_fp (module FP)) + >>=? fun () -> + let epsilon = FP.unsafe_fp Z.one in + fail_unless FP.(ceil epsilon = integral_exn Z.one) (err "ceil eps = 1") + >>=? fun () -> + fail_unless FP.(floor epsilon = integral_exn Z.zero) (err "floor eps = 1") + >>=? fun () -> + let x = Z.of_int (Random.int 980812) in + fail_unless + FP.( + ceil (add (fp (integral_exn x)) (unsafe_fp Z.one)) + = integral_exn (Z.succ x)) + (err "ceil (x + eps) = x + 1") + +let fp_pp () = + let module FP = Gas_limit_repr.Arith in + let prefix msg = Format.asprintf "(%d decimals) %s" 3 msg in + let err msg = err (prefix msg) in + let epsilon = FP.unsafe_fp Z.one in + let ( =:= ) x expected = Format.asprintf "%a" FP.pp x = expected in + fail_unless (epsilon =:= "0.001") (err "eps = 0.001") + >>=? fun () -> + fail_unless (FP.unsafe_fp (Z.of_int 1000) =:= "1") (err "1.000 = 1") + >>=? fun () -> + fail_unless (FP.unsafe_fp (Z.of_int 1001) =:= "1.001") (err "1.001") + >>=? fun () -> + fail_unless (FP.unsafe_fp (Z.of_int 10001) =:= "10.001") (err "10.001") + >>=? fun () -> fail_unless (FP.zero =:= "0") (err "0") + +let tests = + [ Test_services.tztest "Integral tests (3 decimals)" `Quick integral_tests; + Test_services.tztest "FP tests (3 decimals)" `Quick fp_nonzero; + Test_services.tztest "FP pp tests (3 decimals)" `Quick fp_pp ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_gas_costs.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_gas_costs.ml new file mode 100644 index 0000000000000000000000000000000000000000..c0c46af4e7a066939d01713eeae55672f9985047 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_gas_costs.ml @@ -0,0 +1,272 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (gas costs) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^gas cost functions$" + Subject: Gas costs + Current limitations: for maps, sets & compare, we only test + integer comparable keys. +*) + +open Protocol +open Script_ir_translator +module S = Saturation_repr + +let dummy_list = list_cons 42 list_empty + +let forty_two = Alpha_context.Script_int.of_int 42 + +let dummy_set = + set_update forty_two true (empty_set Script_typed_ir.(Int_key None)) + +let dummy_map = + map_update + forty_two + (Some forty_two) + (empty_map Script_typed_ir.(Int_key None)) + +let dummy_timestamp = Alpha_context.Script_timestamp.of_zint (Z.of_int 42) + +let dummy_pk = + Signature.Public_key.of_b58check_exn + "edpkuFrRoDSEbJYgxRtLx2ps82UdaYc1WwfS9sE11yhauZt5DgCHbU" + +let dummy_bytes = Bytes.of_string "dummy" + +let free = ["balance"; "bool"; "parsing_unit"; "unparsing_unit"] + +(* /!\ The compiler will only complain if costs are _removed_ /!\*) +let all_interpreter_costs = + let open Michelson_v1_gas.Cost_of.Interpreter in + [ ("drop", drop); + ("dup", dup); + ("swap", swap); + ("push", push); + ("cons_some", cons_some); + ("cons_none", cons_none); + ("if_none", if_none); + ("cons_pair", cons_pair); + ("car", car); + ("cdr", cdr); + ("cons_left", cons_left); + ("cons_right", cons_right); + ("if_left", if_left); + ("cons_list", cons_list); + ("nil", nil); + ("if_cons", if_cons); + ("list_map", list_map dummy_list); + ("list_size", list_size); + ("list_iter", list_iter dummy_list); + ("empty_set", empty_set); + ("set_iter", set_iter dummy_set); + ("set_mem", set_mem forty_two dummy_set); + ("set_update", set_update forty_two dummy_set); + ("set_size", set_size); + ("empty_map", empty_map); + ("map_map", map_map dummy_map); + ("map_iter", map_iter dummy_map); + ("map_mem", map_mem forty_two dummy_map); + ("map_get", map_get forty_two dummy_map); + ("map_update", map_update forty_two dummy_map); + ("map_size", map_size); + ("add_seconds_timestamp", add_seconds_timestamp forty_two dummy_timestamp); + ("sub_seconds_timestamp", sub_seconds_timestamp forty_two dummy_timestamp); + ("diff_timestamps", diff_timestamps dummy_timestamp dummy_timestamp); + ("concat_string_pair", concat_string_pair "dummy" "dummy"); + ("slice_string", slice_string "dummy"); + ("string_size", string_size); + ("concat_bytes_pair", concat_bytes_pair dummy_bytes dummy_bytes); + ("slice_bytes", slice_bytes dummy_bytes); + ("bytes_size", bytes_size); + ("add_tez", add_tez); + ("sub_tez", sub_tez); + ("mul_teznat", mul_teznat forty_two); + ("bool_or", bool_or); + ("bool_and", bool_and); + ("bool_xor", bool_xor); + ("bool_not", bool_not); + ("is_nat", is_nat); + ("abs_int", abs_int forty_two); + ("int_nat", int_nat); + ("neg_int", neg_int forty_two); + ("neg_nat", neg_nat forty_two); + ("add_bigint", add_bigint forty_two forty_two); + ("sub_bigint", sub_bigint forty_two forty_two); + ("mul_bigint", mul_bigint forty_two forty_two); + ("ediv_teznat", ediv_teznat Alpha_context.Tez.fifty_cents forty_two); + ("ediv_tez", ediv_tez); + ("ediv_bigint", ediv_bigint forty_two (Alpha_context.Script_int.of_int 1)); + ("eq", eq); + ("lsl_nat", lsl_nat forty_two); + ("lsr_nat", lsr_nat forty_two); + ("or_nat", or_nat forty_two forty_two); + ("and_nat", and_nat forty_two forty_two); + ("xor_nat", xor_nat forty_two forty_two); + ("not_int", not_int forty_two); + ("not_nat", not_nat forty_two); + ("seq", seq); + ("if_", if_); + ("loop", loop); + ("loop_left", loop_left); + ("dip", dip); + ("check_signature", check_signature dummy_pk dummy_bytes); + ("blake2b", blake2b dummy_bytes); + ("sha256", sha256 dummy_bytes); + ("sha512", sha512 dummy_bytes); + ("dign", dign 42); + ("dugn", dugn 42); + ("dipn", dipn 42); + ("dropn", dropn 42); + ("neq", neq); + ("nop", nop); + ("compare", compare Script_typed_ir.(Int_key None) forty_two forty_two); + ( "concat_string_precheck", + concat_string_precheck (list_cons "42" list_empty) ); + ("concat_string", concat_string (S.safe_int 42)); + ("concat_bytes", concat_bytes (S.safe_int 42)); + ("exec", exec); + ("apply", apply); + ("lambda", lambda); + ("address", address); + ("contract", contract); + ("transfer_tokens", transfer_tokens); + ("implicit_account", implicit_account); + ("create_contract", create_contract); + ("set_delegate", set_delegate); + (* balance is free *) + ("balance", balance); + ("level", level); + ("now", now); + ("hash_key", hash_key dummy_pk); + ("source", source); + ("sender", sender); + ("self", self); + ("self_address", self_address); + ("amount", amount); + ("chain_id", chain_id); + ("unpack_failed", unpack_failed (Bytes.of_string "dummy")) ] + +(* /!\ The compiler will only complain if costs are _removed_ /!\*) +let all_parsing_costs = + let open Michelson_v1_gas.Cost_of.Typechecking in + [ ("public_key_optimized", public_key_optimized); + ("public_key_readable", public_key_readable); + ("key_hash_optimized", key_hash_optimized); + ("key_hash_readable", key_hash_readable); + ("signature_optimized", signature_optimized); + ("signature_readable", signature_readable); + ("chain_id_optimized", chain_id_optimized); + ("chain_id_readable", chain_id_readable); + ("address_optimized", address_optimized); + ("contract_optimized", contract_optimized); + ("contract_readable", contract_readable); + ("check_printable", check_printable "dummy"); + ("merge_cycle", merge_cycle); + ("parse_type_cycle", parse_type_cycle); + ("parse_instr_cycle", parse_instr_cycle); + ("parse_data_cycle", parse_data_cycle); + ("bool", bool); + ("parsing_unit", unit); + ("timestamp_readable", timestamp_readable); + ("contract", contract); + ("contract_exists", contract_exists); + ("proof_argument", proof_argument 42) ] + +(* /!\ The compiler will only complain if costs are _removed_ /!\*) +let all_unparsing_costs = + let open Michelson_v1_gas.Cost_of.Unparsing in + [ ("public_key_optimized", public_key_optimized); + ("public_key_readable", public_key_readable); + ("key_hash_optimized", key_hash_optimized); + ("key_hash_readable", key_hash_readable); + ("signature_optimized", signature_optimized); + ("signature_readable", signature_readable); + ("chain_id_optimized", chain_id_optimized); + ("chain_id_readable", chain_id_readable); + ("timestamp_readable", timestamp_readable); + ("address_optimized", address_optimized); + ("contract_optimized", contract_optimized); + ("contract_readable", contract_readable); + ("unparse_type_cycle", unparse_type_cycle); + ("unparse_instr_cycle", unparse_instr_cycle); + ("unparse_data_cycle", unparse_data_cycle); + ("unparsing_unit", unit); + ("contract", contract); + ("operation", operation dummy_bytes) ] + +(* /!\ The compiler will only complain if costs are _removed_ /!\*) +let all_io_costs = + let open Storage_costs in + [ ("read_access 0 0", read_access ~path_length:0 ~read_bytes:0); + ("read_access 1 0", read_access ~path_length:1 ~read_bytes:0); + ("read_access 0 1", read_access ~path_length:0 ~read_bytes:1); + ("read_access 1 1", read_access ~path_length:1 ~read_bytes:1); + ("write_access 0", write_access ~written_bytes:0); + ("write_access 1", write_access ~written_bytes:1) ] + +(* Here we're using knowledge of the internal representation of costs to + cast them to S ... *) +let cast_cost_to_s (c : Alpha_context.Gas.cost) : _ S.t = + Data_encoding.Binary.to_bytes_exn Alpha_context.Gas.cost_encoding c + |> Data_encoding.Binary.of_bytes_exn S.n_encoding + +(** Checks that all costs are positive values. *) +let test_cost_reprs_are_all_positive list () = + List.iter_es + (fun (cost_name, cost) -> + if S.(cost > S.zero) then return_unit + else if S.equal cost S.zero && List.mem cost_name free then return_unit + else + fail + (Exn + (Failure (Format.asprintf "Gas cost test \"%s\" failed" cost_name)))) + list + +(** Checks that all costs are positive values. *) +let test_costs_are_all_positive list () = + let list = + List.map (fun (cost_name, cost) -> (cost_name, cast_cost_to_s cost)) list + in + test_cost_reprs_are_all_positive list () + +let tests = + [ Test_services.tztest + "Positivity of interpreter costs" + `Quick + (test_costs_are_all_positive all_interpreter_costs); + Test_services.tztest + "Positivity of typechecking costs" + `Quick + (test_costs_are_all_positive all_parsing_costs); + Test_services.tztest + "Positivity of unparsing costs" + `Quick + (test_costs_are_all_positive all_unparsing_costs); + Test_services.tztest + "Positivity of io costs" + `Quick + (test_cost_reprs_are_all_positive all_io_costs) ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_gas_levels.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_gas_levels.ml new file mode 100644 index 0000000000000000000000000000000000000000..ea3cd6e9ac85858885d775ccb640171b47960e06 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_gas_levels.ml @@ -0,0 +1,142 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Gas levels) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^gas levels$" + Subject: On gas consumption and exhaustion. +*) + +open Protocol +open Raw_context +module S = Saturation_repr + +(* This value is supposed to be larger than the block gas level limit + but not saturated. *) +let opg = max_int / 10000 + +exception Gas_levels_test_error of string + +let err x = Exn (Gas_levels_test_error x) + +let succeed x = match x with Ok _ -> true | _ -> false + +let failed x = not (succeed x) + +let dummy_context () = + Context.init 1 + >>=? fun (block, _) -> + Raw_context.prepare + ~level:Int32.zero + ~predecessor_timestamp:Time.Protocol.epoch + ~timestamp:Time.Protocol.epoch + ~fitness:[] + (block.context : Environment_context.Context.t) + >|= Environment.wrap_tzresult + +let test_detect_gas_exhaustion_in_fresh_context () = + dummy_context () + >>=? fun context -> + fail_unless + (consume_gas context (S.safe_int opg) |> succeed) + (err "In a fresh context, gas consumption is unlimited.") + +let make_context initial_operation_gas = + dummy_context () + >>=? fun context -> + return + ( Gas_limit_repr.Arith.integral_of_int_exn initial_operation_gas + |> set_gas_limit context ) + +let test_detect_gas_exhaustion_when_operation_gas_hits_zero () = + make_context 10 + >>=? fun context -> + fail_unless + (consume_gas context (S.safe_int opg) |> failed) + (err "Fail when consuming more than the remaining operation gas.") + +let test_detect_gas_exhaustion_when_block_gas_hits_zero () = + make_context opg + >>=? fun context -> + fail_unless + (consume_gas context (S.safe_int opg) |> failed) + (err "Fail when consuming more than the remaining block gas.") + +let monitor initial_operation_level gas_level expectation () = + let open Gas_limit_repr.Arith in + make_context initial_operation_level + >>=? fun context -> + fail_unless + ( match consume_gas context (S.safe_int 10000) (* in milligas. *) with + | Ok context -> + let remaining = gas_level context in + remaining = integral_of_int_exn expectation + | _ -> + false ) + (err "Monitor operation gas at each gas consumption") + +let operation_gas_level context = + match gas_level context with + | Gas_limit_repr.Limited {remaining} -> + remaining + | _ -> + (* because this function is called after [set_gas_limit]. *) + assert false + +(* Monitoring runs differently depending on the minimum between the + operation gas level and the block gas level. Hence, we check that + in both situations, the gas levels are correctly reported. *) + +let test_monitor_operation_gas_level = monitor 100 operation_gas_level 90 + +let test_monitor_operation_gas_level' = + monitor opg operation_gas_level (opg - 10) + +let test_monitor_block_gas_level = monitor 100 block_gas_level 10399990 + +let test_monitor_block_gas_level' = monitor opg block_gas_level 10399990 + +let quick (what, how) = Test_services.tztest what `Quick how + +let tests = + List.map + quick + [ ( "Detect gas exhaustion in fresh context", + test_detect_gas_exhaustion_in_fresh_context ); + ( "Detect gas exhaustion when operation gas as hits zero", + test_detect_gas_exhaustion_when_operation_gas_hits_zero ); + ( "Detect gas exhaustion when block gas as hits zero", + test_detect_gas_exhaustion_when_block_gas_hits_zero ); + ( "Each gas consumption impacts operation gas level (operation < block)", + test_monitor_operation_gas_level ); + ( "Each gas consumption impacts operation gas level (block < operation)", + test_monitor_operation_gas_level' ); + ( "Each gas consumption has an impact on block gas level (operation < \ + block)", + test_monitor_block_gas_level ); + ( "Each gas consumption has an impact on block gas level (block < \ + operation)", + test_monitor_block_gas_level' ) ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_gas_properties.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_gas_properties.ml new file mode 100644 index 0000000000000000000000000000000000000000..ae72c19d4d6703086d48badfdf5a85b59026ff6f --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_gas_properties.ml @@ -0,0 +1,172 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (gas properties) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^gas properties$" + Subject: Arithmetic properties around gas. +*) + +open Protocol +module S = Saturation_repr + +type cost_kind = + | Atomic_step + | Step + | Alloc + | Alloc_bytes + | Alloc_mbytes + | Read_bytes + | Write_bytes + +let random_cost_kind () = + let i = Random.int 7 in + match i with + | 0 -> + Atomic_step + | 1 -> + Step + | 2 -> + Alloc + | 3 -> + Alloc_bytes + | 4 -> + Alloc_mbytes + | 5 -> + Read_bytes + | 6 -> + Write_bytes + | _ -> + assert false + +let random_cost_of_kind (cost_kind : cost_kind) = + let open Alpha_context.Gas in + let rand = Random.int 1000 in + match cost_kind with + | Atomic_step -> + atomic_step_cost (S.safe_int rand) + | Step -> + step_cost (S.safe_int rand) + | Alloc -> + alloc_cost (S.safe_int rand) + | Alloc_bytes -> + alloc_bytes_cost rand + | Alloc_mbytes -> + alloc_mbytes_cost rand + | Read_bytes -> + read_bytes_cost rand + | Write_bytes -> + write_bytes_cost rand + +let random_cost () = random_cost_of_kind (random_cost_kind ()) + +(** Consuming [Gas.free] is equivalent to consuming nothing. *) +let test_free_neutral since = + let open Alpha_context in + let open Environment.Error_monad in + let cost = random_cost () in + Gas.consume since cost + >>? fun ctxt -> + Gas.consume ctxt Gas.free + >>? fun branch1 -> + Gas.consume since cost + >>? fun branch2 -> + if + Gas.Arith.( + Gas.consumed ~since:ctxt ~until:branch1 + = Gas.consumed ~since:ctxt ~until:branch2) + then ok_none + else Ok (Some (cost, Gas.free)) + +(** Consuming [cost1] then [cost2] is equivalent to consuming + [Gas.(cost1 +@ cost2)]. *) +let test_consume_commutes since = + let open Alpha_context in + let open Environment.Error_monad in + let cost1 = random_cost () in + let cost2 = random_cost () in + Gas.consume since cost1 + >>? fun ctxt -> + Gas.consume ctxt cost2 + >>? fun branch1 -> + Gas.consume since Gas.(cost1 +@ cost2) + >>? fun branch2 -> + if + Gas.Arith.( + Gas.consumed ~since:ctxt ~until:branch1 + = Gas.consumed ~since:ctxt ~until:branch2) + then ok_none + else Ok (Some (cost1, cost2)) + +let rec loop_check check n ctxt = + let open Environment.Error_monad in + if n = 0 then ok_none + else + check ctxt + >>? function + | None -> + loop_check check (n - 1) ctxt + | counterexample -> + Ok counterexample + +let check_property prop () = + Random.init 89809344 ; + Context.init 1 + >>=? fun (b, _contracts) -> + Incremental.begin_construction b + >>=? fun inc -> + let state = Incremental.validation_state inc in + let ctxt = + Alpha_context.Gas.set_limit + state.ctxt + Alpha_context.Gas.Arith.(fp (integral_of_int_exn 100_000_000)) + in + let result = prop ctxt in + match result with + | Ok None -> + return_unit + | Ok (Some (cost1, cost2)) -> + let msg = + Format.asprintf + "gas consume commutation falsified for %a ; %a" + Alpha_context.Gas.pp_cost + cost1 + Alpha_context.Gas.pp_cost + cost2 + in + failwith "%s" msg + | Error _err -> + failwith "gas_consume_commutes: protocol error" + +let tests = + [ Test_services.tztest + "Gas.free is a neutral element" + `Quick + (check_property (loop_check test_free_neutral 1000)); + Test_services.tztest + "Gas.consume commutes" + `Quick + (check_property (loop_check test_consume_commutes 1000)) ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_helpers_rpcs.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_helpers_rpcs.ml new file mode 100644 index 0000000000000000000000000000000000000000..ff6af9a0c1ec571bf7add58d7d8f95e513185eda --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_helpers_rpcs.ml @@ -0,0 +1,78 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Helpers RPCs) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^helpers rpcs$" + Subject: On RPCs. +*) + +open Protocol +open Alpha_context + +(* Test the baking_rights RPC. + Future levels or cycles are not tested because it's hard in this framework, + using only RPCs, to fabricate them. *) +let test_baking_rights () = + Context.init 2 + >>=? fun (b, contracts) -> + let open Alpha_services.Delegate.Baking_rights in + (* default max_priority returns 65 results *) + get Block.rpc_ctxt b ~all:true + >>=? fun rights -> + assert (List.length rights = 65) ; + (* arbitrary max_priority *) + let max_priority = 15 in + get Block.rpc_ctxt b ~all:true ~max_priority + >>=? fun rights -> + assert (List.length rights = max_priority + 1) ; + (* filtering by delegate *) + let d = + Option.bind (List.nth contracts 0) Contract.is_implicit + |> WithExceptions.Option.get ~loc:__LOC__ + in + get Block.rpc_ctxt b ~all:true ~delegates:[d] + >>=? fun rights -> + assert (List.for_all (fun {delegate; _} -> delegate = d) rights) ; + (* filtering by cycle *) + Alpha_services.Helpers.current_level Block.rpc_ctxt b + >>=? fun {cycle; _} -> + get Block.rpc_ctxt b ~all:true ~cycles:[cycle] + >>=? fun rights -> + Alpha_services.Helpers.levels_in_current_cycle Block.rpc_ctxt b + >>=? fun (first, last) -> + assert ( + List.for_all (fun {level; _} -> level >= first && level <= last) rights ) ; + (* filtering by level *) + Alpha_services.Helpers.current_level Block.rpc_ctxt b + >>=? fun {level; _} -> + get Block.rpc_ctxt b ~all:true ~levels:[level] + >>=? fun rights -> + let espected_level = level in + assert (List.for_all (fun {level; _} -> level = espected_level) rights) ; + return_unit + +let tests = [Test_services.tztest "baking_rights" `Quick test_baking_rights] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_interpretation.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_interpretation.ml new file mode 100644 index 0000000000000000000000000000000000000000..de7b4a165bd23fe91a58b2cc37e44ca63dbfb5e3 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_interpretation.ml @@ -0,0 +1,183 @@ +(** Testing + ------- + Component: Protocol (interpretation) + Dependencies: src/proto_alpha/lib_protocol/script_interpreter.ml + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^interpretation$" + Subject: Interpretation of Michelson scripts +*) + +open Protocol +open Alpha_context +open Script_interpreter + +let ( >>=?? ) x y = + x + >>= function + | Ok s -> + y s + | Error err -> + Lwt.return @@ Error (Environment.wrap_tztrace err) + +let test_context () = + Context.init 3 + >>=? fun (b, _cs) -> + Incremental.begin_construction b + >>=? fun v -> return (Incremental.alpha_ctxt v) + +let default_source = Contract.implicit_contract Signature.Public_key_hash.zero + +let default_step_constants = + { + source = default_source; + payer = default_source; + self = default_source; + amount = Tez.zero; + chain_id = Chain_id.zero; + } + +(** Helper function that parses and types a script, its initial storage and + parameters from strings. It then executes the typed script with the storage + and parameter and returns the result. *) +let run_script ctx ?(step_constants = default_step_constants) contract + ?(entrypoint = "default") ~storage ~parameter () = + let contract_expr = Expr.from_string contract in + let storage_expr = Expr.from_string storage in + let parameter_expr = Expr.from_string parameter in + let script = + Script.{code = lazy_expr contract_expr; storage = lazy_expr storage_expr} + in + Script_interpreter.execute + ctx + Readable + step_constants + ~script + ~entrypoint + ~parameter:parameter_expr + ~internal:false + >>=?? fun res -> return res + +module Logger : STEP_LOGGER = struct + let log_interp _ctxt _descr _stack = () + + let log_entry _ctxt _descr _stack = () + + let log_exit _ctxt _descr _stack = () + + let get_log () = Lwt.return (Ok None) +end + +let run_step ctxt code param = + Script_interpreter.step + (module Logger) + ctxt + default_step_constants + code + param + +(** Runs a script with an ill-typed parameter and verifies that a + Bad_contract_parameter error is returned. *) +let test_bad_contract_parameter () = + test_context () + >>=? fun ctx -> + (* Run script with a parameter of wrong type *) + run_script + ctx + "{parameter unit; storage unit; code { CAR; NIL operation; PAIR }}" + ~storage:"Unit" + ~parameter:"0" + () + >>= function + | Ok _ -> + Alcotest.fail "expected an error" + | Error (Environment.Ecoproto_error (Bad_contract_parameter source') :: _) -> + Test_services.(check Testable.contract) + "incorrect field in Bad_contract_parameter" + default_source + source' ; + return_unit + | Error errs -> + Alcotest.failf "Unexpected error: %a" Error_monad.pp_print_error errs + +let read_file filename = + let ch = open_in filename in + let s = really_input_string ch (in_channel_length ch) in + close_in ch ; s + +(* Check that too many recursive calls of the Michelson interpreter result in an error *) +let test_stack_overflow () = + test_context () + >>=? fun ctxt -> + let descr instr = + Script_typed_ir.{loc = 0; bef = Empty_t; aft = Empty_t; instr} + in + let enorme_et_seq n = + let rec aux n acc = + if n = 0 then acc else aux (n - 1) (descr (Seq (acc, descr Nop))) + in + aux n (descr Nop) + in + run_step ctxt (enorme_et_seq 10_001) () + >>= function + | Ok _ -> + Alcotest.fail "expected an error" + | Error trace -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + let expect = + "Too many recursive calls were needed for interpretation of a \ + Michelson script" + in + if Astring.String.is_infix ~affix:expect trace_string then return_unit + else Alcotest.failf "Unexpected error (%s) at %s" trace_string __LOC__ + +(** Test the encoding/decoding of script_interpreter.ml specific errors *) +let test_json_roundtrip name testable enc v = + let v' = + Data_encoding.Json.destruct enc (Data_encoding.Json.construct enc v) + in + Alcotest.check + testable + (Format.asprintf "round trip should not change value of %s" name) + v + v' ; + return_unit + +(** Encoding/decoding of script_interpreter.ml specific errors. *) +let test_json_roundtrip_err name e () = + test_json_roundtrip + name + Testable.protocol_error + Environment.Error_monad.error_encoding + e + +let error_encoding_tests = + let contract_zero = + Contract.implicit_contract Signature.Public_key_hash.zero + in + let script_expr_int = + Micheline.strip_locations (Micheline.Int (0, Z.zero)) + in + List.map + (fun (name, e) -> + Test_services.tztest + (Format.asprintf "test error encoding: %s" name) + `Quick + (test_json_roundtrip_err name e)) + [ ("Reject", Reject (0, script_expr_int, None)); + ("Overflow", Overflow (0, None)); + ( "Runtime_contract_error", + Runtime_contract_error (contract_zero, script_expr_int) ); + ("Bad_contract_parameter", Bad_contract_parameter contract_zero); + ("Cannot_serialize_log", Helpers_services.Cannot_serialize_log); + ("Cannot_serialize_failure", Cannot_serialize_failure); + ("Cannot_serialize_storage", Cannot_serialize_storage) ] + +let tests = + [ Test_services.tztest + "test bad contract error" + `Quick + test_bad_contract_parameter; + Test_services.tztest "test stack overflow error" `Slow test_stack_overflow + ] + @ error_encoding_tests diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_lazy_storage_diff.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_lazy_storage_diff.ml new file mode 100644 index 0000000000000000000000000000000000000000..a5a69f58ad103d3dd5b2d6b85548d2458e2b80ca --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_lazy_storage_diff.ml @@ -0,0 +1,143 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** Generation of input data *) + +let ids = + [|1; 42; 1337; 1984|] |> Array.map Z.of_int + |> Array.map Lazy_storage_kind.Big_map.Id.parse_z + +let strs = [|"0"; "True"; "nat"; "bool"|] + +let exprs = strs |> Array.map Expr.from_string + +let hashes = + strs |> Array.map (fun x -> [x]) |> Array.map Script_expr_hash.hash_string + +let updates_len_existing = [1; 2; 3] + +let updates_len_other = 0 :: updates_len_existing + +let gen_inits idx : + ( ( Lazy_storage_kind.Big_map.Id.t, + Lazy_storage_kind.Big_map.alloc ) + Lazy_storage_diff.init + * int list ) + list = + [ (Existing, updates_len_existing); + (Copy {src = ids.(idx - 1)}, updates_len_other); + ( Alloc {key_type = exprs.(idx); value_type = exprs.(idx - 1)}, + updates_len_other ) ] + +let gen_update_list idx : Lazy_storage_kind.Big_map.update list = + [None; Some exprs.(idx)] + |> List.map (fun value -> + Lazy_storage_kind.Big_map. + {key = exprs.(idx); key_hash = hashes.(idx); value}) + +let rec gen_updates updates_len : Lazy_storage_kind.Big_map.updates list = + if updates_len = 0 then [] + else + gen_updates (updates_len - 1) + |> List.map (fun suffix -> + gen_update_list updates_len + |> List.map (fun prefix -> prefix :: suffix)) + |> List.flatten + +let gen_updates_list updates_lens : Lazy_storage_kind.Big_map.updates list = + updates_lens |> List.map gen_updates |> List.flatten + +let gen_diffs idx : + ( Lazy_storage_kind.Big_map.Id.t, + Lazy_storage_kind.Big_map.alloc, + Lazy_storage_kind.Big_map.updates ) + Lazy_storage_diff.diff + list = + let open Lazy_storage_diff in + Remove + :: ( gen_inits idx + |> List.map (fun (init, updates_lens) -> + gen_updates_list updates_lens + |> List.map (fun updates -> Update {init; updates})) + |> List.flatten ) + +let gen_diffs_items idx : Lazy_storage_diff.diffs_item list = + let id = ids.(idx) in + gen_diffs idx + |> List.map (fun diff -> Lazy_storage_diff.make Big_map id diff) + +let rec gen_diffs_list len : Lazy_storage_diff.diffs list = + if len = 0 then [] + else + gen_diffs_list (len - 1) + |> List.map (fun suffix -> + gen_diffs_items len |> List.map (fun prefix -> prefix :: suffix)) + |> List.flatten + +let diffs_list_lens = [0; 1; 2; 3] + +let diffs_list : Lazy_storage_diff.diffs list = + diffs_list_lens |> List.map gen_diffs_list |> List.flatten + +(** Properties to check *) + +let conversion_roundtrip lazy_storage_diff = + let legacy_big_map_diff = + Contract_storage.Legacy_big_map_diff.of_lazy_storage_diff lazy_storage_diff + in + let reconverted = + Contract_storage.Legacy_big_map_diff.to_lazy_storage_diff + legacy_big_map_diff + in + assert (Stdlib.( = ) reconverted lazy_storage_diff) + +let encoding_roundtrip lazy_storage_diff = + let encoded = + Data_encoding.Binary.to_bytes_exn + Lazy_storage_diff.encoding + lazy_storage_diff + in + match Data_encoding.Binary.of_bytes Lazy_storage_diff.encoding encoded with + | Ok decoded -> + assert (Stdlib.( = ) decoded lazy_storage_diff) + | Error _ -> + Stdlib.failwith "Decoding failed" + +(** Iterator and test definitions *) + +let on_diffs f () = List.iter f diffs_list ; return_unit + +(* Marked Slow because they take 5 to 10 seconds and are unlikely to change *) +let tests = + [ Test_services.tztest + "conversion roundtrip" + `Slow + (on_diffs conversion_roundtrip); + Test_services.tztest + "encoding roundtrip" + `Slow + (on_diffs encoding_roundtrip) ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_origination.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_origination.ml new file mode 100644 index 0000000000000000000000000000000000000000..3d3a7fb80e28939c829d1bb4d28ba2cef3d5e09d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_origination.ml @@ -0,0 +1,261 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (origination) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^origination$" + Subject: On originating contracts. +*) + +open Protocol +open Test_tez + +let ten_tez = Tez.of_int 10 + +(** [register_origination fee credit spendable delegatable] takes four + optional parameter: fee for the fee need to be paid if set to + create an originated contract; credit is the amount of tez that + send to this originated contract; spendable default is set to true + meaning that this contract is spendable; delegatable default is + set to true meaning that this contract is able to delegate. *) +let register_origination ?(fee = Tez.zero) ?(credit = Tez.zero) () = + Context.init 1 + >>=? fun (b, contracts) -> + let source = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts in + Context.Contract.balance (B b) source + >>=? fun source_balance -> + Op.origination (B b) source ~fee ~credit ~script:Op.dummy_script + >>=? fun (operation, originated) -> + Block.bake ~operation b + >>=? fun b -> + (* fee + credit + block security deposit were debited from source *) + Context.get_constants (B b) + >>=? fun { parametric = + {origination_size; cost_per_byte; block_security_deposit; _}; + _ } -> + Tez.(cost_per_byte *? Int64.of_int origination_size) + >>?= fun origination_burn -> + Tez.( +? ) credit block_security_deposit + >>? Tez.( +? ) fee + >>? Tez.( +? ) origination_burn + >>? Tez.( +? ) Op.dummy_script_cost + >>?= fun total_fee -> + Assert.balance_was_debited ~loc:__LOC__ (B b) source source_balance total_fee + >>=? fun () -> + (* originated contract has been credited *) + Assert.balance_was_credited ~loc:__LOC__ (B b) originated Tez.zero credit + >|=? fun () -> + (* TODO spendable or not and delegatable or not if relevant for some + test. Not the case at the moment, cf. uses of + register_origination *) + (b, source, originated) + +(* [test_origination_balances fee credit spendable delegatable] + takes four optional parameter: fee is the fee that pay if require to create + an originated contract; credit is the amount of tez that will send to this + contract; delegatable default is set to true meaning that this contract is + able to delegate. + This function will create a contract, get the balance of this contract, call + the origination operation to create a new originated contract from this + contract with all the possible fees; and check the balance before/after + originated operation valid. + - the source contract has payed all the fees + - the originated has been credited correctly *) +let test_origination_balances ~loc:_ ?(fee = Tez.zero) ?(credit = Tez.zero) () + = + Context.init 1 + >>=? fun (b, contracts) -> + let contract = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts in + Context.Contract.balance (B b) contract + >>=? fun balance -> + Op.origination (B b) contract ~fee ~credit ~script:Op.dummy_script + >>=? fun (operation, new_contract) -> + (* The possible fees are: a given credit, an origination burn fee + (constants_repr.default.origination_burn = 257 mtez), + a fee that is paid when creating an originate contract. + + We also take into account a block security deposit. Note that it + is not related to origination but to the baking done in the + tests.*) + Context.get_constants (B b) + >>=? fun { parametric = + {origination_size; cost_per_byte; block_security_deposit; _}; + _ } -> + Tez.(cost_per_byte *? Int64.of_int origination_size) + >>?= fun origination_burn -> + Tez.( +? ) credit block_security_deposit + >>? Tez.( +? ) fee + >>? Tez.( +? ) origination_burn + >>? Tez.( +? ) Op.dummy_script_cost + >>?= fun total_fee -> + Block.bake ~operation b + >>=? fun b -> + (* check that after the block has been baked the source contract + was debited all the fees *) + Assert.balance_was_debited ~loc:__LOC__ (B b) contract balance total_fee + >>=? fun _ -> + (* check the balance of the originate contract is equal to credit *) + Assert.balance_is ~loc:__LOC__ (B b) new_contract credit + +(******************************************************) +(* Tests *) +(******************************************************) + +(** compute half of the balance and divided it by nth times *) + +let two_nth_of_balance incr contract nth = + Context.Contract.balance (I incr) contract + >>=? fun balance -> + Lwt.return (Tez.( /? ) balance nth >>? fun res -> Tez.( *? ) res 2L) + +(** Basic test. A contract is created as well as the newly originated + contract (called from origination operation). The balance + before/after are checked. *) +let test_balances_simple () = test_origination_balances ~loc:__LOC__ () + +(** Same as [balances_simple] but credits 10 tez to the originated + contract (no fees). *) +let test_balances_credit () = + test_origination_balances ~loc:__LOC__ ~credit:ten_tez () + +(** Same as [balances_credit] with 10 tez fees. *) +let test_balances_credit_fee () = + test_origination_balances ~loc:__LOC__ ~credit:(Tez.of_int 2) ~fee:ten_tez () + +(** Ask source contract to pay a fee when originating a contract. *) +let test_pay_fee () = + register_origination ~credit:(Tez.of_int 2) ~fee:ten_tez () + >>=? fun (_b, _contract, _new_contract) -> return_unit + +(******************************************************) +(** Errors *) + +(******************************************************) + +(** Create an originate contract where the contract does not have + enough tez to pay for the fee. *) +let test_not_tez_in_contract_to_pay_fee () = + Context.init 2 + >>=? fun (b, contracts) -> + let contract_1 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 + in + let contract_2 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 1 + in + Incremental.begin_construction b + >>=? fun inc -> + (* transfer everything but one tez from 1 to 2 and check balance of 1 *) + Context.Contract.balance (I inc) contract_1 + >>=? fun balance -> + Tez.( -? ) balance Tez.one + >>?= fun amount -> + Op.transaction (I inc) contract_1 contract_2 amount + >>=? fun operation -> + Incremental.add_operation inc operation + >>=? fun inc -> + Assert.balance_was_debited ~loc:__LOC__ (I inc) contract_1 balance amount + >>=? fun _ -> + (* use this source contract to create an originate contract where it requires + to pay a fee and add an amount of credit into this new contract *) + Op.origination + (I inc) + ~fee:ten_tez + ~credit:Tez.one + contract_1 + ~script:Op.dummy_script + >>=? fun (op, _) -> + Incremental.add_operation inc op + >>= fun inc -> + Assert.proto_error ~loc:__LOC__ inc (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + +(* Set the endorser of the block as manager/delegate of the originated + account. *) +let register_contract_get_endorser () = + Context.init 1 + >>=? fun (b, contracts) -> + let contract = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts in + Incremental.begin_construction b + >>=? fun inc -> + Context.get_endorser (I inc) + >|=? fun (account_endorser, _slots) -> (inc, contract, account_endorser) + +(* Create multiple originated contracts and ask contract to pay the fee. *) +let n_originations n ?credit ?fee () = + List.fold_left_es + (fun new_contracts _ -> + register_origination ?fee ?credit () + >|=? fun (_b, _source, new_contract) -> new_contract :: new_contracts) + [] + (1 -- n) + +(** Create 100 originations. *) +let test_multiple_originations () = + n_originations 100 ~credit:(Tez.of_int 2) ~fee:ten_tez () + >>=? fun contracts -> + Assert.equal_int ~loc:__LOC__ (List.length contracts) 100 + +(** Cannot originate two contracts with the same context's counter. *) +let test_counter () = + Context.init 1 + >>=? fun (b, contracts) -> + let contract = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts in + Incremental.begin_construction b + >>=? fun inc -> + Op.origination (I inc) ~credit:Tez.one contract ~script:Op.dummy_script + >>=? fun (op1, _) -> + Op.origination (I inc) ~credit:Tez.one contract ~script:Op.dummy_script + >>=? fun (op2, _) -> + Incremental.add_operation inc op1 + >>=? fun inc -> + Incremental.add_operation inc op2 + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Contract_storage.Counter_in_the_past _ -> + true + | _ -> + false) + +(******************************************************) + +let tests = + [ Test_services.tztest "balances_simple" `Quick test_balances_simple; + Test_services.tztest "balances_credit" `Quick test_balances_credit; + Test_services.tztest "balances_credit_fee" `Quick test_balances_credit_fee; + Test_services.tztest "pay_fee" `Quick test_pay_fee; + Test_services.tztest + "not enough tez in contract to pay fee" + `Quick + test_not_tez_in_contract_to_pay_fee; + Test_services.tztest + "multiple originations" + `Quick + test_multiple_originations; + Test_services.tztest "counter" `Quick test_counter ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_qty.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_qty.ml new file mode 100644 index 0000000000000000000000000000000000000000..94567cae4376eaab3b03bc727783447a1457c4cb --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_qty.ml @@ -0,0 +1,163 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (quantities) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^qty$" + Subject: On tez quantities. +*) + +open Protocol + +let known_ok_tez_literals = + [ (0L, "0"); + (10L, "0.00001"); + (100L, "0.0001"); + (1_000L, "0.001"); + (10_000L, "0.01"); + (100_000L, "0.1"); + (1_000_000L, "1"); + (10_000_000L, "10"); + (100_000_000L, "100"); + (1_000_000_000L, "1000"); + (10_000_000_000L, "10000"); + (100_000_000_000L, "100000"); + (1_000_000_000_000L, "1000000"); + (1_000_000_000_001L, "1000000.000001"); + (1_000_000_000_010L, "1000000.00001"); + (1_000_000_000_100L, "1000000.0001"); + (1_000_000_001_000L, "1000000.001"); + (1_000_000_010_000L, "1000000.01"); + (1_000_000_100_000L, "1000000.1"); + (123_123_123_123_123_123L, "123123123123.123123"); + (999_999_999_999_999_999L, "999999999999.999999") ] + +let known_bad_tez_literals = + [ "10000."; + "100,."; + "100,"; + "1,0000"; + "0.0000,1"; + "0.00,1"; + "0,1"; + "HAHA"; + "0.000,000,1"; + "0.0000000"; + "9,999,999,999,999.999,999" ] + +let fail expected given msg = + Format.kasprintf + Stdlib.failwith + "@[%s@ expected: %s@ got: %s@]" + msg + expected + given + +let fail_msg fmt = Format.kasprintf (fail "" "") fmt + +let default_printer _ = "" + +(** Literals which are supposed to be parsed correctly. *) +let test_known_tez_literals () = + List.iter + (fun (v, s) -> + let vv = Tez_repr.of_mutez v in + let vs = Tez_repr.of_string s in + let vs' = + Tez_repr.of_string (String.concat "" (String.split_on_char ',' s)) + in + let vv = + match vv with + | None -> + fail_msg "could not unopt %Ld" v + | Some vv -> + vv + in + let vs = + match vs with None -> fail_msg "could not unopt %s" s | Some vs -> vs + in + let vs' = + match vs' with + | None -> + fail_msg "could not unopt %s" s + | Some vs' -> + vs' + in + assert (vv = vs) ; + assert (vv = vs') ; + assert (Tez_repr.to_string vv = s)) + known_ok_tez_literals ; + List.iter + (fun s -> + let vs = Tez_repr.of_string s in + assert (vs = None)) + known_bad_tez_literals ; + return_unit + +(** Randomly generated tez value which is printed into a string then + parsed again for their equality. *) +let test_random_tez_literals () = + for _ = 0 to 100_000 do + let v = Random.int64 12L in + let vv = Tez_repr.of_mutez v in + let vv = + match vv with None -> fail_msg "could not unopt %Ld" v | Some vv -> vv + in + let s = Tez_repr.to_string vv in + let vs = Tez_repr.of_string s in + let s' = String.concat "" (String.split_on_char ',' s) in + let vs' = Tez_repr.of_string s' in + assert (vs <> None) ; + assert (vs' <> None) ; + ( match vs with + | None -> + assert false + | Some vs -> + let rev = Tez_repr.to_int64 vs in + assert (v = rev) ) ; + match vs' with + | None -> + assert false + | Some vs' -> + let rev = Tez_repr.to_int64 vs' in + assert (v = rev) + done ; + return_unit + +let tests = + [ ("tez-literals", fun _ -> test_known_tez_literals ()); + ("rnd-tez-literals", fun _ -> test_random_tez_literals ()) ] + +let wrap (n, f) = + Alcotest_lwt.test_case n `Quick (fun _ () -> + f () + >|= function + | Ok () -> + () + | Error error -> + Format.kasprintf Stdlib.failwith "%a" pp_print_error error) + +let tests = List.map wrap tests diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_reveal.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_reveal.ml new file mode 100644 index 0000000000000000000000000000000000000000..090db07e91bc5eee29c8dda43462ca0ba869667e --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_reveal.ml @@ -0,0 +1,131 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (revelation) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^revelation$" + Subject: On the reveal operation. +*) + +(** Test for the [Reveal] operation. *) + +open Protocol +open Test_tez + +let ten_tez = Tez.of_int 10 + +let test_simple_reveal () = + Context.init 1 + >>=? fun (blk, contracts) -> + let c = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts in + let new_c = Account.new_account () in + let new_contract = Alpha_context.Contract.implicit_contract new_c.pkh in + (* Create the contract *) + Op.transaction (B blk) c new_contract Tez.one + >>=? fun operation -> + Block.bake blk ~operation + >>=? fun blk -> + Context.Contract.is_manager_key_revealed (B blk) new_contract + >|=? (function + | true -> Stdlib.failwith "Unexpected revelation" | false -> ()) + >>=? fun () -> + (* Reveal the contract *) + Op.revelation (B blk) new_c.pk + >>=? fun operation -> + Block.bake blk ~operation + >>=? fun blk -> + Context.Contract.is_manager_key_revealed (B blk) new_contract + >|=? function + | true -> () | false -> Stdlib.failwith "New contract revelation failed." + +let test_empty_account_on_reveal () = + Context.init 1 + >>=? fun (blk, contracts) -> + let c = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts in + let new_c = Account.new_account () in + let new_contract = Alpha_context.Contract.implicit_contract new_c.pkh in + let amount = Tez.one_mutez in + (* Create the contract *) + Op.transaction (B blk) c new_contract amount + >>=? fun operation -> + Block.bake blk ~operation + >>=? fun blk -> + Context.Contract.is_manager_key_revealed (B blk) new_contract + >|=? (function + | true -> Stdlib.failwith "Unexpected revelation" | false -> ()) + >>=? fun () -> + (* Reveal the contract *) + Op.revelation ~fee:amount (B blk) new_c.pk + >>=? fun operation -> + Incremental.begin_construction blk + >>=? fun inc -> + Incremental.add_operation inc operation + >>=? fun _ -> + Block.bake blk ~operation + >>=? fun blk -> + Context.Contract.is_manager_key_revealed (B blk) new_contract + >|=? function + | false -> + () + | true -> + Stdlib.failwith "Empty account still exists and is revealed." + +let test_not_enough_found_for_reveal () = + Context.init 1 + >>=? fun (blk, contracts) -> + let c = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts in + let new_c = Account.new_account () in + let new_contract = Alpha_context.Contract.implicit_contract new_c.pkh in + (* Create the contract *) + Op.transaction (B blk) c new_contract Tez.one_mutez + >>=? fun operation -> + Block.bake blk ~operation + >>=? fun blk -> + Context.Contract.is_manager_key_revealed (B blk) new_contract + >|=? (function + | true -> Stdlib.failwith "Unexpected revelation" | false -> ()) + >>=? fun () -> + (* Reveal the contract *) + Op.revelation ~fee:Tez.fifty_cents (B blk) new_c.pk + >>=? fun operation -> + Block.bake blk ~operation + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Contract_storage.Balance_too_low _ -> + true + | _ -> + false) + +let tests = + [ Test_services.tztest "simple reveal" `Quick test_simple_reveal; + Test_services.tztest + "empty account on reveal" + `Quick + test_empty_account_on_reveal; + Test_services.tztest + "not enough found for reveal" + `Quick + test_not_enough_found_for_reveal ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_rolls.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_rolls.ml new file mode 100644 index 0000000000000000000000000000000000000000..dd2af08f8742dfd82fd2b3c05cf9768e554f4bbc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_rolls.ml @@ -0,0 +1,357 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (rolls) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^rolls$" + Subject: On rolls and baking rights. + A delegate has baking rights provided that it has at least + more than [token_per_rolls] tz of staking balance. This + balance corresponds to the quantity of tez that have been + delegated to it for baking rights. After a given number of + cycles where it has not made use of its baking rights, its + account will be deactivated for baker selection. To bake + again, it will have to re-activate its account. +*) + +open Protocol +open Alpha_context +open Test_tez + +let account_pair = function [a1; a2] -> (a1, a2) | _ -> assert false + +let wrap e = Lwt.return (Environment.wrap_tzresult e) + +(** Baking rights consistency. Assert that the number of rolls for + [account]'s pkh - equals to the number of expected rolls, i.e., + staking balance of [account] / (token_per_roll). As of protocol + version 007, token_per_roll = 8000. Note that the consistency is + verified against the value in the context, i.e. we are testing + Storage.Roll.Delegate_roll_list. We do not use RPCs here. *) +let check_rolls (b : Block.t) (account : Account.t) = + Context.get_constants (B b) + >>=? fun constants -> + Context.Delegate.info (B b) account.pkh + >>=? fun {staking_balance; _} -> + let token_per_roll = constants.parametric.tokens_per_roll in + let expected_rolls = + Int64.div (Tez.to_mutez staking_balance) (Tez.to_mutez token_per_roll) + in + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun ctxt -> + Roll_storage.count_rolls ctxt account.pkh + >>= wrap + >>=? fun rolls -> + Assert.equal_int ~loc:__LOC__ rolls (Int64.to_int expected_rolls) + +let check_no_rolls (b : Block.t) (account : Account.t) = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun ctxt -> + Roll_storage.count_rolls ctxt account.pkh + >>= wrap + >>=? fun rolls -> Assert.equal_int ~loc:__LOC__ rolls 0 + +(** Create a block with two initialized contracts/accounts. Assert + that the first account has a staking balance that is equal to its + own balance, and that its staking rights are consistent + (check_rolls). *) +let test_simple_staking_rights () = + Context.init 2 + >>=? fun (b, accounts) -> + let (a1, _a2) = account_pair accounts in + Context.Contract.balance (B b) a1 + >>=? fun balance -> + Context.Contract.manager (B b) a1 + >>=? fun m1 -> + Context.Delegate.info (B b) m1.pkh + >>=? fun info -> + Assert.equal_tez ~loc:__LOC__ balance info.staking_balance + >>=? fun () -> check_rolls b m1 + +(** Create a block with two initialized contracts/accounts. Bake + five blocks. Assert that the staking balance of the first account + equals to its balance. Then both accounts have consistent staking + rights. *) +let test_simple_staking_rights_after_baking () = + Context.init 2 + >>=? fun (b, accounts) -> + let (a1, a2) = account_pair accounts in + Context.Contract.balance (B b) a1 + >>=? fun balance -> + Context.Contract.manager (B b) a1 + >>=? fun m1 -> + Context.Contract.manager (B b) a2 + >>=? fun m2 -> + Block.bake_n ~policy:(By_account m2.pkh) 5 b + >>=? fun b -> + Context.Delegate.info (B b) m1.pkh + >>=? fun info -> + Assert.equal_tez ~loc:__LOC__ balance info.staking_balance + >>=? fun () -> check_rolls b m1 >>=? fun () -> check_rolls b m2 + +let frozen_deposit (info : Context.Delegate.info) = + Cycle.Map.fold + (fun _ {Delegate.deposit; _} acc -> Test_tez.Tez.(deposit + acc)) + info.frozen_balance_by_cycle + Tez.zero + +let check_activate_staking_balance ~loc ~deactivated b (a, (m : Account.t)) = + Context.Delegate.info (B b) m.pkh + >>=? fun info -> + Assert.equal_bool ~loc info.deactivated deactivated + >>=? fun () -> + Context.Contract.balance (B b) a + >>=? fun balance -> + let deposit = frozen_deposit info in + Assert.equal_tez ~loc Test_tez.Tez.(balance + deposit) info.staking_balance + +let run_until_deactivation () = + Context.init 2 + >>=? fun (b, accounts) -> + let (a1, a2) = account_pair accounts in + Context.Contract.balance (B b) a1 + >>=? fun balance_start -> + Context.Contract.manager (B b) a1 + >>=? fun m1 -> + Context.Contract.manager (B b) a2 + >>=? fun m2 -> + check_activate_staking_balance ~loc:__LOC__ ~deactivated:false b (a1, m1) + >>=? fun () -> + Context.Delegate.info (B b) m1.pkh + >>=? fun info -> + Block.bake_until_cycle ~policy:(By_account m2.pkh) info.grace_period b + >>=? fun b -> + check_activate_staking_balance ~loc:__LOC__ ~deactivated:false b (a1, m1) + >>=? fun () -> + Block.bake_until_cycle_end ~policy:(By_account m2.pkh) b + >>=? fun b -> + check_activate_staking_balance ~loc:__LOC__ ~deactivated:true b (a1, m1) + >|=? fun () -> (b, ((a1, m1), balance_start), (a2, m2)) + +(** From an initialized block with two contracts/accounts, the first + one is active then deactivated. After baking, check that the + account is active again. Baking rights are ensured. *) +let test_deactivation_then_bake () = + run_until_deactivation () + >>=? fun ( b, + ( ((_deactivated_contract, deactivated_account) as deactivated), + _start_balance ), + (_a2, _m2) ) -> + Block.bake ~policy:(By_account deactivated_account.pkh) b + >>=? fun b -> + check_activate_staking_balance ~loc:__LOC__ ~deactivated:false b deactivated + >>=? fun () -> check_rolls b deactivated_account + +(** A deactivated account, after baking with self-delegation, is + active again. Preservation of its balance is tested. Baking rights + are ensured. *) +let test_deactivation_then_self_delegation () = + run_until_deactivation () + >>=? fun ( b, + ( ((deactivated_contract, deactivated_account) as deactivated), + start_balance ), + (_a2, m2) ) -> + Op.delegation (B b) deactivated_contract (Some deactivated_account.pkh) + >>=? fun self_delegation -> + Block.bake ~policy:(By_account m2.pkh) b ~operation:self_delegation + >>=? fun b -> + check_activate_staking_balance ~loc:__LOC__ ~deactivated:false b deactivated + >>=? fun () -> + Context.Contract.balance (B b) deactivated_contract + >>=? fun balance -> + Assert.equal_tez ~loc:__LOC__ start_balance balance + >>=? fun () -> check_rolls b deactivated_account + +(** A deactivated account, which is emptied (into a newly created sink + account), then self-delegated, becomes activated. Its balance is + zero. Baking rights are ensured. *) +let test_deactivation_then_empty_then_self_delegation () = + run_until_deactivation () + >>=? fun ( b, + ( ((deactivated_contract, deactivated_account) as deactivated), + _start_balance ), + (_a2, m2) ) -> + (* empty the contract *) + Context.Contract.balance (B b) deactivated_contract + >>=? fun balance -> + let sink_account = Account.new_account () in + let sink_contract = Contract.implicit_contract sink_account.pkh in + Context.get_constants (B b) + >>=? fun {parametric = {origination_size; cost_per_byte; _}; _} -> + Tez.(cost_per_byte *? Int64.of_int origination_size) + >>?= fun origination_burn -> + let amount = + match Tez.(balance -? origination_burn) with + | Ok r -> + r + | Error _ -> + assert false + in + Op.transaction (B b) deactivated_contract sink_contract amount + >>=? fun empty_contract -> + Block.bake ~policy:(By_account m2.pkh) ~operation:empty_contract b + >>=? fun b -> + (* self delegation *) + Op.delegation (B b) deactivated_contract (Some deactivated_account.pkh) + >>=? fun self_delegation -> + Block.bake ~policy:(By_account m2.pkh) ~operation:self_delegation b + >>=? fun b -> + check_activate_staking_balance ~loc:__LOC__ ~deactivated:false b deactivated + >>=? fun () -> + Context.Contract.balance (B b) deactivated_contract + >>=? fun balance -> + Assert.equal_tez ~loc:__LOC__ Tez.zero balance + >>=? fun () -> check_rolls b deactivated_account + +(** A deactivated account, which is emptied, then self-delegated, then + re-credited of the sunk amount, becomes active again. Staking + rights remain consistent. *) +let test_deactivation_then_empty_then_self_delegation_then_recredit () = + run_until_deactivation () + >>=? fun ( b, + ( ((deactivated_contract, deactivated_account) as deactivated), + balance ), + (_a2, m2) ) -> + (* empty the contract *) + let sink_account = Account.new_account () in + let sink_contract = Contract.implicit_contract sink_account.pkh in + Context.get_constants (B b) + >>=? fun {parametric = {origination_size; cost_per_byte; _}; _} -> + Tez.(cost_per_byte *? Int64.of_int origination_size) + >>?= fun origination_burn -> + let amount = + match Tez.(balance -? origination_burn) with + | Ok r -> + r + | Error _ -> + assert false + in + Op.transaction (B b) deactivated_contract sink_contract amount + >>=? fun empty_contract -> + Block.bake ~policy:(By_account m2.pkh) ~operation:empty_contract b + >>=? fun b -> + (* self delegation *) + Op.delegation (B b) deactivated_contract (Some deactivated_account.pkh) + >>=? fun self_delegation -> + Block.bake ~policy:(By_account m2.pkh) ~operation:self_delegation b + >>=? fun b -> + (* recredit *) + Op.transaction (B b) sink_contract deactivated_contract amount + >>=? fun recredit_contract -> + Block.bake ~policy:(By_account m2.pkh) ~operation:recredit_contract b + >>=? fun b -> + check_activate_staking_balance ~loc:__LOC__ ~deactivated:false b deactivated + >>=? fun () -> + Context.Contract.balance (B b) deactivated_contract + >>=? fun balance -> + Assert.equal_tez ~loc:__LOC__ amount balance + >>=? fun () -> check_rolls b deactivated_account + +(** Initialize a block with two contracts/accounts. A third new + account is also created. The first account is self-delegated. First + account sends to third one the amount of 0.5 tez. The third account + has no delegate and is consistent for baking rights. Then, it is + self-delegated and is supposed to be activated. Again, consistency + for baking rights are preserved for the first and third accounts. *) +let test_delegation () = + Context.init 2 + >>=? fun (b, accounts) -> + let (a1, a2) = account_pair accounts in + let m3 = Account.new_account () in + Account.add_account m3 ; + Context.Contract.manager (B b) a1 + >>=? fun m1 -> + Context.Contract.manager (B b) a2 + >>=? fun m2 -> + let a3 = Contract.implicit_contract m3.pkh in + Context.Contract.delegate_opt (B b) a1 + >>=? fun delegate -> + ( match delegate with + | None -> + assert false + | Some pkh -> + assert (Signature.Public_key_hash.equal pkh m1.pkh) ) ; + Op.transaction (B b) a1 a3 Tez.fifty_cents + >>=? fun transact -> + Block.bake ~policy:(By_account m2.pkh) b ~operation:transact + >>=? fun b -> + Context.Contract.delegate_opt (B b) a3 + >>=? fun delegate -> + (match delegate with None -> () | Some _ -> assert false) ; + check_no_rolls b m3 + >>=? fun () -> + Op.delegation (B b) a3 (Some m3.pkh) + >>=? fun delegation -> + Block.bake ~policy:(By_account m2.pkh) b ~operation:delegation + >>=? fun b -> + Context.Contract.delegate_opt (B b) a3 + >>=? fun delegate -> + ( match delegate with + | None -> + assert false + | Some pkh -> + assert (Signature.Public_key_hash.equal pkh m3.pkh) ) ; + check_activate_staking_balance ~loc:__LOC__ ~deactivated:false b (a3, m3) + >>=? fun () -> check_rolls b m3 >>=? fun () -> check_rolls b m1 + +let tests = + [ Test_services.tztest + "simple staking rights" + `Quick + test_simple_staking_rights; + Test_services.tztest + "simple staking rights after baking" + `Quick + test_simple_staking_rights_after_baking; + Test_services.tztest + "deactivation then bake" + `Quick + test_deactivation_then_bake; + Test_services.tztest + "deactivation then self delegation" + `Quick + test_deactivation_then_self_delegation; + Test_services.tztest + "deactivation then empty then self delegation" + `Quick + test_deactivation_then_empty_then_self_delegation; + Test_services.tztest + "deactivation then empty then self delegation then recredit" + `Quick + test_deactivation_then_empty_then_self_delegation_then_recredit; + Test_services.tztest "delegation" `Quick test_delegation ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_sapling.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_sapling.ml new file mode 100644 index 0000000000000000000000000000000000000000..a5c31e96f2c1239bbafff02bfec96861f9cf0277 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_sapling.ml @@ -0,0 +1,1286 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Sapling) + Invocation: cd src/proto_alpha/lib_protocol/test + dune exec ./main.exe -- test "^sapling$" + Subject: On the privacy-preserving library Sapling +*) + +open Protocol + +module Raw_context_tests = struct + open Sapling_helpers.Common + + (* This test adds to the first 100 positions in the commitments tree the + constant value `uncommitted` for which we know the corresponding root and + tests that the returned root is as expected. *) + let commitments_add_uncommitted () = + Context.init 1 + >>=? fun (b, _) -> + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun ctx -> + let module H = Tezos_sapling.Core.Client.Hash in + let cm = H.uncommitted ~height:0 in + let expected_root = H.uncommitted ~height:32 in + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + >>= wrap + >>=? fun (ctx, id) -> + Sapling_storage.init ctx id ~memo_size:0 + >>= wrap + >>=? fun ctx -> + List.fold_left_es + (fun ctx pos -> + Sapling_storage.Commitments.get_root ctx id + >>= wrap + >>=? fun (ctx, root) -> + assert (root = expected_root) ; + Sapling_storage.Commitments.add + ctx + id + [H.to_commitment cm] + (Int64.of_int pos) + >>= wrap + >>=? fun (ctx, _size) -> + Sapling_storage.Commitments.get_root ctx id + >>= wrap + >|=? fun (ctx, root) -> + assert (root = expected_root) ; + ctx) + ctx + (0 -- 99) + >>=? fun _ctx -> return_unit + + (* Nullifiers don't check for duplicates are it's done by verify_update, + however committing to disk twice the same nf causes a storage error by + trying to initialize the same key twice. *) + let nullifier_double () = + Context.init 1 + >>=? fun (b, _) -> + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun ctx -> + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + >>= wrap + >>=? fun (ctx, id) -> + Sapling_storage.init ctx id ~memo_size:0 + >>= wrap + >>=? fun ctx -> + let nf = gen_nf () in + let open Sapling_storage in + let state = + {id = Some id; diff = Sapling_storage.empty_diff; memo_size = 0} + in + let state = nullifiers_add state nf in + let state = nullifiers_add state nf in + assert (List.length state.diff.nullifiers = 2) ; + Sapling_storage.Nullifiers.size ctx id + >>= wrap + >>=? fun disk_size -> + assert (disk_size = 0L) ; + Sapling_storage.apply_diff ctx id state.diff |> assert_error + + (* In this test we add two lists of nullifiers to the state, one is applied to + the context (committed to disk) and one is kept in kept in a diff (only in + memory). We then check that nullifier_mem answers true for those two lists + and false for a third one. *) + let nullifier_test () = + Context.init 1 + >>=? fun (b, _) -> + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun ctx -> + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + >>= wrap + >>=? fun (ctx, id) -> + Sapling_storage.init ctx id ~memo_size:0 + >>= wrap + >>=? fun ctx -> + let nf_list_ctx = + List.init ~when_negative_length:() 10 (fun _ -> gen_nf ()) + |> function + | Error () -> assert false (* 10 > 0 *) | Ok nf_list_ctx -> nf_list_ctx + in + let state = + List.fold_left + (fun state nf -> Sapling_storage.nullifiers_add state nf) + {id = Some id; diff = Sapling_storage.empty_diff; memo_size = 0} + nf_list_ctx + in + Sapling_storage.apply_diff ctx id state.diff + >>= wrap + >>=? fun (ctx, _) -> + let nf_list_diff = + List.init ~when_negative_length:() 10 (fun _ -> gen_nf ()) + |> function + | Error () -> assert false (* 10 > 0 *) | Ok nf_list_diff -> nf_list_diff + in + let state = + List.fold_left + (fun state nf -> Sapling_storage.nullifiers_add state nf) + state + nf_list_diff + in + List.iter_ep + (fun nf -> + Sapling_storage.nullifiers_mem ctx state nf + >>= wrap + >>=? fun (_, bool) -> + assert bool ; + return_unit) + (nf_list_ctx @ nf_list_diff) + >>=? fun () -> + let nf_list_absent = + List.init 10 ~when_negative_length:() (fun _ -> gen_nf ()) + |> function + | Error () -> + assert false (* 10 > 0 *) + | Ok nf_list_absent -> + nf_list_absent + in + List.iter_ep + (fun nf -> + Sapling_storage.nullifiers_mem ctx state nf + >>= wrap + >>=? fun (_, bool) -> + assert (not bool) ; + return_unit) + nf_list_absent + + (* This test applies a diff with tuples of ciphertext, commitment. Then it + checks the result of get_from with different indexes. *) + let cm_cipher_test () = + Random.self_init () ; + let memo_size = Random.int 200 in + Context.init 1 + >>=? fun (b, _) -> + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun ctx -> + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + >>= wrap + >>=? fun (ctx, id) -> + Sapling_storage.init ctx id ~memo_size + >>= wrap + >>=? fun ctx -> + Sapling_storage.state_from_id ctx id + >>= wrap + >>=? fun (diff, ctx) -> + let list_added = + List.init ~when_negative_length:() 10 (fun _ -> + gen_cm_cipher ~memo_size ()) + |> function + | Error () -> assert false (* 10 > 0 *) | Ok list_added -> list_added + in + let state = Sapling_storage.add diff list_added in + Sapling_storage.apply_diff ctx id state.diff + >>= wrap + >>=? fun (ctx, _) -> + let rec test_from from until expected = + if from > until then return_unit + else + Sapling_storage.Ciphertexts.get_from ctx id from + >>= wrap + >>=? fun (ctx, result) -> + let expected_cipher = List.map snd expected in + assert (result = expected_cipher) ; + Sapling_storage.Commitments.get_from ctx id from + >>= wrap + >>=? fun result -> + let expected_cm = List.map fst expected in + assert (result = expected_cm) ; + test_from + (Int64.succ from) + until + (WithExceptions.Option.get ~loc:__LOC__ @@ List.tl expected) + in + test_from 0L 9L list_added + + (* This test tests the insertion of a list vs inserting one by one. + It does so by checking the equality of the roots. *) + let list_insertion_test () = + Random.self_init () ; + let memo_size = Random.int 200 in + Context.init 1 + >>=? fun (b, _) -> + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun ctx -> + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + >>= wrap + >>=? fun (ctx, id_one_by_one) -> + Sapling_storage.init ctx id_one_by_one ~memo_size + >>= wrap + >>=? fun ctx -> + let list_to_add = + fst @@ List.split + @@ ( List.init ~when_negative_length:() 33 (fun _ -> + gen_cm_cipher ~memo_size ()) + |> function Error () -> assert false (* 33 > 0 *) | Ok r -> r ) + in + let rec test counter ctx = + if counter >= 32 then return_unit + else + (* add a single cm to the existing tree *) + Sapling_storage.Commitments.add + ctx + id_one_by_one + [ WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth list_to_add counter ] + (Int64.of_int counter) + >>= wrap + (* create a new tree and add a list of cms *) + >>=? fun (ctx, _size) -> + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + >>= wrap + >>=? fun (ctx, id_all_at_once) -> + Sapling_storage.init ctx id_all_at_once ~memo_size + >>= wrap + >>=? fun ctx -> + Sapling_storage.Commitments.add + ctx + id_all_at_once + ( List.init ~when_negative_length:() (counter + 1) (fun i -> + WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth list_to_add i) + |> function Error () -> assert false (* counter >= 0*) | Ok r -> r ) + 0L + >>= wrap + >>=? fun (ctx, _size) -> + Sapling_storage.Commitments.get_root ctx id_one_by_one + >>= wrap + >>=? fun (ctx, root_one_by_one) -> + Sapling_storage.Commitments.get_root ctx id_all_at_once + >>= wrap + >>=? fun (ctx, root_all_at_once) -> + assert (root_all_at_once = root_one_by_one) ; + test (counter + 1) ctx + in + test 0 ctx + + (* This test adds 10 more roots the maximum capacity, all at different + levels, and checks that all but the first 10 are stored. + Then it adds one in the diff and checks it is stored. + Then it adds 10 at the same level and check that only the last one is + stored. *) + let root_test () = + let open Tezos_sapling.Core in + let gen_root () = + Data_encoding.Binary.of_bytes_exn + Validator.Hash.encoding + (Hacl.Rand.gen 32) + in + let roots_ctx = + List.init + ~when_negative_length:() + (Int32.to_int Sapling_storage.Roots.size + 10) + (fun _ -> gen_root ()) + |> function + | Error () -> assert false (* size >= 0 *) | Ok roots_ctx -> roots_ctx + in + Context.init 1 + >>=? fun (b, _) -> + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun ctx -> + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + >>= wrap + >>=? fun (ctx, id) -> + Sapling_storage.init ctx id ~memo_size:0 + >>= wrap + >>=? fun ctx -> + (* Add one root per level to the context *) + List.fold_left_es + (fun (ctx, cnt) root -> + Sapling_storage.Roots.add ctx id root + >>= wrap + >>=? fun ctx -> + (* Very low level way to "bake" a block. It would be better to use the + helpers functions but they complicate the access to the raw_context. *) + Raw_context.prepare + ~level:(Int32.add b.header.shell.level cnt) + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + (Raw_context.recover ctx) + >>= wrap + >|=? fun ctx -> (ctx, Int32.succ cnt)) + (ctx, 0l) + roots_ctx + >>=? fun (ctx, _) -> + (* Check mem on all the roots in the context. *) + let state = + Sapling_storage. + {id = Some id; diff = Sapling_storage.empty_diff; memo_size = 0} + in + List.fold_left_es + (fun i root -> + Sapling_storage.root_mem ctx state root + >>= wrap + >|=? fun bool -> + assert (if i < 10 then not bool else bool) ; + i + 1) + 0 + roots_ctx + >>=? fun _ -> + (* Add roots w/o increasing the level *) + let roots_same_level = + List.init ~when_negative_length:() 10 (fun _ -> gen_root ()) + |> function + | Error () -> + assert false (* 10 > 0 *) + | Ok roots_same_level -> + roots_same_level + in + List.fold_left_es + (fun ctx root -> Sapling_storage.Roots.add ctx id root >>= wrap) + ctx + roots_same_level + >>=? fun ctx -> + List.fold_left_es + (fun (i, ctx) root -> + Sapling_storage.root_mem ctx state root + >>= wrap + >|=? fun bool -> + assert (if i < 9 then not bool else bool) ; + (i + 1, ctx)) + (0, ctx) + roots_same_level + >>=? fun _ -> return_unit + + let test_get_memo_size () = + Context.init 1 + >>=? fun (b, _) -> + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~fitness:b.header.shell.fitness + >>= wrap + >>=? fun ctx -> + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + >>= wrap + >>=? fun (ctx, id) -> + Sapling_storage.init ctx id ~memo_size:0 + >>= wrap + >>=? fun ctx -> + Sapling_storage.get_memo_size ctx id + >>= wrap + >|=? fun memo_size -> assert (memo_size = 0) +end + +module Alpha_context_tests = struct + open Sapling_helpers.Alpha_context_helpers + + (* Create a transaction with memo_size 1, test that is validates with a newly + created empty_state with memo_size 1 and does not with memo_size 0. *) + let test_verify_memo () = + init () + >>=? fun ctx -> + let sk = + Tezos_sapling.Core.Wallet.Spending_key.of_seed + (Tezos_crypto.Hacl.Rand.gen 32) + in + let vt = + let ps = Tezos_sapling.Storage.empty ~memo_size:0 in + (* the dummy output will have memo_size 0 *) + Tezos_sapling.Forge.forge_transaction + ~number_dummy_outputs:1 + [] + [] + sk + "anti-replay" + ps + in + verify_update ctx vt ~memo_size:0 + |> assert_some + >>=? fun _ -> verify_update ctx vt ~memo_size:1 |> assert_none + + (* Bench the proving and validation time of shielding and transferring several + tokens. *) + let test_bench_phases () = + init () + >>=? fun ctx -> + let rounds = 5 in + Printf.printf "\nrounds: %d\n" rounds ; + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + (* one verify_update to get the id *) + let vt = transfer w cs [] in + verify_update ctx vt |> assert_some + >>=? fun (ctx, id) -> + client_state_alpha ctx id + >>=? fun cs -> + let start = Unix.gettimeofday () in + let vts = List.map (fun _ -> transfer w cs []) (1 -- rounds) in + let ctime_shields = Unix.gettimeofday () -. start in + Printf.printf "client_shields %f\n" ctime_shields ; + let start = Unix.gettimeofday () in + List.fold_left_es + (fun ctx vt -> + verify_update ctx ~id vt |> assert_some >|=? fun (ctx, _id) -> ctx) + ctx + vts + >>=? fun ctx -> + let vtime_shields = Unix.gettimeofday () -. start in + Printf.printf "valdtr_shields %f\n" vtime_shields ; + client_state_alpha ctx id + >>=? fun cs -> + let start = Unix.gettimeofday () in + let vts = List.map (fun i -> transfer w cs [i]) (1 -- rounds) in + let ctime_transfers = Unix.gettimeofday () -. start in + Printf.printf "client_txs %f\n" ctime_transfers ; + let start = Unix.gettimeofday () in + List.fold_left_es + (fun ctx vt -> + verify_update ctx ~id vt |> assert_some >|=? fun (ctx, _id) -> ctx) + ctx + vts + >|=? fun _ctx -> + let vtime_transfers = Unix.gettimeofday () -. start in + Printf.printf "valdtr_txs %f\n" vtime_transfers + + (* Transfer several times the same token. *) + let test_bench_fold_over_same_token () = + init () + >>=? fun ctx -> + let rounds = 5 in + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + (* one verify_update to get the id *) + let vt = transfer w cs [] in + verify_update ctx vt |> assert_some + >>=? fun (ctx, id) -> + let rec loop cnt ctx = + if cnt >= rounds then return_unit + else + (* inefficient: re-synch from scratch at each round *) + client_state_alpha ctx id + >>=? fun cs -> + let vt = transfer w cs [cnt] in + verify_update ctx ~id vt |> assert_some + >>=? fun (ctx, _id) -> loop (cnt + 1) ctx + in + loop 0 ctx + + (* + The following tests trigger all the branches of + Sapling_validator.verify_update. + The function performs several checks and returns None in case of failure. + During development the function was modified to throw a different exception + for each of its checks so to be sure that they were reached. + *) + + (* Test that double spending the same input fails the nf check. *) + let test_double_spend_same_input () = + init () + >>=? fun ctx -> + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + (* one verify_update to get the id *) + let vt = transfer w cs [] in + verify_update ctx vt |> assert_some + >>=? fun (ctx, id) -> + client_state_alpha ctx id + >>=? fun cs -> + let vt = transfer w cs [0] in + verify_update ctx ~id vt |> assert_some + >>=? fun (_ctx, id) -> + let vt = transfer w cs [0; 0] in + verify_update ctx ~id vt |> assert_none + + let test_verifyupdate_one_transaction () = + init () + >>=? fun ctx -> + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + let vt = transfer w cs [] in + verify_update ctx vt |> assert_some + >>=? fun (ctx, id) -> + client_state_alpha ctx id + >>=? fun cs -> + let vt = transfer w cs [0] in + (* fails sig check because of wrong balance *) + let vt_broken = + Tezos_sapling.Core.Validator.UTXO. + {vt with balance = Int64.(succ vt.balance)} + in + verify_update ctx ~id vt_broken + |> assert_none + >>=? fun () -> + (* randomize one output to fail check outputs *) + (* don't randomize the ciphertext as it is not part of the proof *) + let open Tezos_sapling.Core.Client.UTXO in + let o = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd vt.outputs in + let o_wrong_cm = + { + o with + cm = randomized_byte o.cm Tezos_sapling.Core.Client.Commitment.encoding; + } + in + let vt_broken = + Tezos_sapling.Core.Validator.UTXO.{vt with outputs = [o_wrong_cm]} + in + verify_update ctx ~id vt_broken + |> assert_none + >>=? fun () -> + (* position inside the cv *) + let pos = Random.int 32 in + let o_wrong_cv = + { + o with + ciphertext = + randomized_byte + ~pos + o.ciphertext + Tezos_sapling.Core.Client.Ciphertext.encoding; + } + in + let vt_broken = + Tezos_sapling.Core.Validator.UTXO.{vt with outputs = [o_wrong_cv]} + in + verify_update ctx ~id vt_broken |> assert_none + + let test_verifyupdate_two_transactions () = + init () + >>=? fun ctx -> + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + (* generate the first storage *) + let vt = transfer w cs [] in + verify_update ctx vt |> assert_some + >>=? fun (ctx, id1) -> + client_state_alpha ctx id1 + >>=? fun cs1 -> + let vt1 = transfer w cs1 [0] in + (* generate the second storage *) + let vt = transfer w cs [] in + verify_update ctx vt |> assert_some + >>=? fun (ctx, id2) -> + client_state_alpha ctx id2 + >>=? fun cs2 -> + let vt2 = transfer w cs2 [0] in + (* fail root check *) + verify_update ctx ~id:id1 vt2 + |> assert_none + >>=? fun () -> + (* Swap the root so that it passes the root_mem check but fails + the input check *) + let vt1_broken = + Tezos_sapling.Core.Validator.UTXO.{vt2 with root = vt1.root} + in + verify_update ctx ~id:id1 vt1_broken + |> assert_none + >>=? fun () -> + (* fail the sig check *) + let vt1_broken = + Tezos_sapling.Core.Validator.UTXO.{vt1 with outputs = vt2.outputs} + in + verify_update ctx ~id:id1 vt1_broken |> assert_none +end + +module Interpreter_tests = struct + open Sapling_helpers.Interpreter_helpers + + let parameters_of_list transactions = + let string = "{ " ^ String.concat " ; " transactions ^ " }" in + Alpha_context.Script.(lazy_expr (expression_from_string string)) + + (* In this test we use a contract which takes a list of transactions, applies + all of them, and assert all of them are correct. It also enforces a 1-to-1 + conversion with mutez by asking an amount to shield and asking for a pkh to + unshield. + We create 2 keys a and b. We originate the contract, then do two lists of + shield for a, then transfers several outputs to b while unshielding, then + transfer all of b inputs to a while adding dummy inputs and outputs. + At last we fail we make a failing transaction. *) + let test_shielded_tez () = + init () + >>=? fun (b, baker, src0, src1) -> + let memo_size = 8 in + originate_contract "contracts/sapling_contract.tz" "{ }" src0 b baker + >>=? fun (dst, b, anti_replay) -> + let wa = wallet_gen () in + let (list_transac, total) = + shield + ~memo_size + wa.sk + 4 + wa.vk + (Format.sprintf "Pair 0x%s None") + anti_replay + in + let parameters = parameters_of_list list_transac in + (* a does a list of shield transaction *) + transac_and_sync ~memo_size b parameters total src0 dst baker + >>=? fun (b, _ctx, _state) -> + (* we shield again on another block, forging with the empty state *) + let (list_transac, total) = + shield + ~memo_size + wa.sk + 4 + wa.vk + (Format.sprintf "Pair 0x%s None") + anti_replay + in + let parameters = parameters_of_list list_transac in + (* a does a list of shield transaction *) + transac_and_sync ~memo_size b parameters total src0 dst baker + >>=? fun (b, ctx, state) -> + (* address that will receive an unshield *) + Alpha_context.Contract.get_balance ctx src1 + >>= wrap + >>=? fun balance_before_shield -> + let wb = wallet_gen () in + let list_addr = gen_addr 15 wb.vk in + let list_forge_input = + List.init ~when_negative_length:() 14 (fun pos_int -> + let pos = Int64.of_int pos_int in + let forge_input = + snd + ( Tezos_sapling.Forge.Input.get state pos wa.vk + |> WithExceptions.Option.get ~loc:__LOC__ ) + in + forge_input) + |> function + | Error () -> + assert false (* 14 > 0 *) + | Ok list_forge_input -> + list_forge_input + in + let list_forge_output = + List.map + (fun addr -> Tezos_sapling.Forge.make_output addr 1L (Bytes.create 8)) + list_addr + in + let hex_transac = + to_hex + (Tezos_sapling.Forge.forge_transaction + ~number_dummy_inputs:0 + ~number_dummy_outputs:0 + list_forge_input + list_forge_output + wa.sk + anti_replay + state) + Tezos_sapling.Core.Client.UTXO.transaction_encoding + in + let hex_pkh = + to_hex + ( Alpha_context.Contract.is_implicit src1 + |> WithExceptions.Option.get ~loc:__LOC__ ) + Signature.Public_key_hash.encoding + in + let string = + Format.sprintf "{Pair 0x%s (Some 0x%s) }" hex_transac hex_pkh + in + let parameters = + Alpha_context.Script.(lazy_expr (expression_from_string string)) + in + (* a transfers to b and unshield some money to src_2 (the pkh) *) + transac_and_sync ~memo_size b parameters 0 src0 dst baker + >>=? fun (b, ctx, state) -> + Alpha_context.Contract.get_balance ctx src1 + >>= wrap + >>=? fun balance_after_shield -> + let diff = + Int64.sub + (Test_tez.Tez.to_mutez balance_after_shield) + (Test_tez.Tez.to_mutez balance_before_shield) + in + (* The inputs total [total] mutez and 15 of those are transfered in shielded tez *) + assert (Int64.equal diff (Int64.of_int (total - 15))) ; + let list_forge_input = + List.init ~when_negative_length:() 15 (fun i -> + let pos = Int64.of_int (i + 14 + 14) in + let forge_input = + snd + ( Tezos_sapling.Forge.Input.get state pos wb.vk + |> WithExceptions.Option.get ~loc:__LOC__ ) + in + forge_input) + |> function + | Error () -> + assert false (* 14 > 0 *) + | Ok list_forge_input -> + list_forge_input + in + let addr_a = + snd + @@ Tezos_sapling.Core.Client.Viewing_key.new_address + wa.vk + Tezos_sapling.Core.Client.Viewing_key.default_index + in + let output = Tezos_sapling.Forge.make_output addr_a 15L (Bytes.create 8) in + let hex_transac = + to_hex + (Tezos_sapling.Forge.forge_transaction + ~number_dummy_inputs:2 + ~number_dummy_outputs:2 + list_forge_input + [output] + wb.sk + anti_replay + state) + Tezos_sapling.Core.Client.UTXO.transaction_encoding + in + let string = Format.sprintf "{Pair 0x%s None }" hex_transac in + let parameters = + Alpha_context.Script.(lazy_expr (expression_from_string string)) + in + (* b transfers to a with dummy inputs and outputs *) + transac_and_sync ~memo_size b parameters 0 src0 dst baker + >>=? fun (b, _ctx, _state) -> + (* Here we fail by doing the same transaction again*) + Incremental.begin_construction b + >>=? fun incr -> + let fee = Test_tez.Tez.of_int 10 in + Op.transaction ~fee (B b) src0 dst Test_tez.Tez.zero ~parameters + >>=? fun operation -> + Incremental.add_operation (* TODO make more precise *) + ~expect_failure:(fun _ -> return_unit) + incr + operation + >>=? fun _incr -> return_unit + + let test_push_sapling_state_should_be_forbidden () = + init () + (* Originating a contract to get a sapling_state with ID 0, used in the next contract *) + >>=? fun (block, baker, src, _) -> + originate_contract "contracts/sapling_contract.tz" "{ }" src block baker + >>=? fun _ -> + (* Originating the next contract should fail *) + originate_contract + "contracts/sapling_push_sapling_state.tz" + "{ }" + src + block + baker + >>= function + | Error + [ Environment.Ecoproto_error (Script_tc_errors.Ill_typed_contract _); + Environment.Ecoproto_error + (Script_tc_errors.Unexpected_lazy_storage _) ] -> + return_unit + | _ -> + assert false + + let test_use_state_from_other_contract_and_transact () = + (* + Attempt to use a sapling state of a contract A in a contract B + *) + init () + (* Originating the contracts *) + >>=? fun (block, baker, src, _) -> + let memo_size = 8 in + (* originate_contract "contracts/sapling_contract.tz" "{ }" src block baker + >>=? fun (_shielded_pool_contract_address, block, _anti_replay_shielded_pool) + -> *) + originate_contract + "contracts/sapling_use_existing_state.tz" + "{ }" + src + block + baker + >>=? fun (existing_state_contract_address, block, anti_replay_2) -> + (* we create one shielding transaction and transform it in Micheline to use + it as a parameter + *) + let wa = wallet_gen () in + let (transactions, _total) = + shield + ~memo_size + wa.sk + 1 + wa.vk + (Format.sprintf "(Pair 0x%s 0)") + anti_replay_2 + in + let transaction = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd transactions + in + let parameters = + Alpha_context.Script.(lazy_expr (expression_from_string transaction)) + in + transac_and_sync + ~memo_size + block + parameters + 0 + src + existing_state_contract_address + baker + >|= function + | Ok _ -> + Alcotest.failf "Unexpected operations success" + | Error errs -> + assert ( + List.exists + (function + | Environment.Ecoproto_error + (Tezos_raw_protocol_009_PsFLoren.Script_tc_errors + .Unexpected_forged_value _) -> + true + | _ -> + false) + errs ) ; + ok_unit + + (* In this test we do two transactions in one block and same two in two block. + We check that the sate is the same expect for roots. + The second transaction is possible only if the first one is done. *) + let test_transac_and_block () = + init () + >>=? fun (b, baker, src, _) -> + let memo_size = 8 in + originate_contract "contracts/sapling_contract.tz" "{ }" src b baker + >>=? fun (dst, block_start, anti_replay) -> + let {sk; vk} = wallet_gen () in + let hex_transac_1 = hex_shield ~memo_size {sk; vk} anti_replay in + let string_1 = Format.sprintf "{Pair %s None }" hex_transac_1 in + let parameters_1 = + Alpha_context.Script.(lazy_expr (expression_from_string string_1)) + in + transac_and_sync ~memo_size block_start parameters_1 15 src dst baker + >>=? fun (block_1, _ctx, state) -> + let intermediary_root = Tezos_sapling.Storage.get_root state in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.(new_address vk default_index) + in + let output = Tezos_sapling.Forge.make_output addr 15L (Bytes.create 8) in + let hex_transac_2 = + "0x" + ^ to_hex + (Tezos_sapling.Forge.forge_transaction + [ snd + ( Tezos_sapling.Forge.Input.get state 0L vk + |> WithExceptions.Option.get ~loc:__LOC__ ) ] + [output] + sk + anti_replay + state) + Tezos_sapling.Core.Client.UTXO.transaction_encoding + in + let string_2 = Format.sprintf "{Pair %s None }" hex_transac_2 in + let parameters_2 = + Alpha_context.Script.(lazy_expr (expression_from_string string_2)) + in + transac_and_sync ~memo_size block_1 parameters_2 0 src dst baker + >>=? fun (block_1, _ctx, state_1) -> + let final_root = Tezos_sapling.Storage.get_root state_1 in + Alpha_services.Contract.single_sapling_get_diff + Block.rpc_ctxt + block_1 + dst + ~offset_commitment:0L + ~offset_nullifier:0L + () + >>=? fun (_root, diff_1) -> + let fee = Test_tez.Tez.of_int 10 in + Test_tez.Tez.(one_mutez *? Int64.of_int 15) + >>?= fun amount_tez -> + Op.transaction + ~fee + (B block_start) + src + dst + amount_tez + ~parameters:parameters_1 + >>=? fun operation -> + Incremental.begin_construction block_start + >>=? fun incr -> + Incremental.add_operation incr operation + >>=? fun incr -> + (* We need to manually get the counter here *) + let ctx = Incremental.alpha_ctxt incr in + let pkh = + Alpha_context.Contract.is_implicit src + |> WithExceptions.Option.get ~loc:__LOC__ + in + Alpha_context.Contract.get_counter ctx pkh + >>= wrap + >>=? fun counter -> + Op.transaction + ~counter + ~fee + (B block_start) + src + dst + Test_tez.Tez.zero + ~parameters:parameters_2 + >>=? fun operation -> + Incremental.add_operation incr operation + >>=? fun incr -> + Incremental.finalize_block incr + >>=? fun block_2 -> + Alpha_services.Contract.single_sapling_get_diff + Block.rpc_ctxt + block_2 + dst + ~offset_commitment:0L + ~offset_nullifier:0L + () + >>=? fun (_root, diff_2) -> + (* We check that the same transactions have passed *) + assert (diff_1 = diff_2) ; + let is_root_in block dst root = + Incremental.begin_construction block + >>=? fun incr -> + let ctx_2 = Incremental.alpha_ctxt incr in + Alpha_services.Contract.script Block.rpc_ctxt block dst + >>=? fun script -> + let ctx_without_gas_2 = Alpha_context.Gas.set_unlimited ctx_2 in + Script_ir_translator.parse_script + ctx_without_gas_2 + ~legacy:true + ~allow_forged_in_storage:true + script + >>= wrap + >>=? fun (Ex_script script, ctxt) -> + Script_ir_translator.get_single_sapling_state + ctxt + script.storage_type + script.storage + |> wrap + >>=? fun (id, _ctx_2) -> + let id = + Lazy_storage_kind.Sapling_state.Id.parse_z + @@ Alpha_context.Sapling.Id.unparse_to_z id + in + Raw_context.prepare + block.context + ~level:block.header.shell.level + ~predecessor_timestamp:block.header.shell.timestamp + ~timestamp:block.header.shell.timestamp + ~fitness:block.header.shell.fitness + >>= wrap + >>=? fun raw_ctx -> Sapling_storage.Roots.mem raw_ctx id root >>= wrap + in + (* We check that the second state did not store the root in between + transactions. *) + is_root_in block_2 dst intermediary_root + |> assert_false + >>=? fun () -> + (* We check that the second state did store the final root. *) + is_root_in block_2 dst final_root + |> assert_true + >>=? fun () -> + (* We check that the first state did store the final root. *) + is_root_in block_1 dst final_root + |> assert_true + >>=? fun () -> + (* We check that the first state did store the root in between transactions. *) + is_root_in block_1 dst intermediary_root |> assert_true + + (* In this test we try a contract which creates an empty sapling state on the + fly. It then applies a list of transactions, checks they are correct and + drops the result. We make several shields in the same list (since the state + is drop). *) + let test_drop () = + init () + >>=? fun (b, baker, src, _) -> + originate_contract "contracts/sapling_contract_drop.tz" "Unit" src b baker + >>=? fun (dst, b, anti_replay) -> + let {sk; vk} = wallet_gen () in + let (list_transac, _total) = + shield ~memo_size:8 sk 4 vk (Format.sprintf "0x%s") anti_replay + in + let parameters = parameters_of_list list_transac in + Op.transaction + ~fee:(Test_tez.Tez.of_int 10) + (B b) + src + dst + Test_tez.Tez.zero + ~parameters + >>=? fun operation -> next_block b operation >>=? fun _b -> return_unit + + (* We use a contrac with two states. Its parameter is two transactions and a + bool. The two transactions are tested valid against the two states, but + only one state according to the bool is updated. + We do two transactions shielding to different keys in the two states. + At each transactions both are applied but only state is updated. + We then check that the first state is updated in the correct way. *) + let test_double () = + init () + >>=? fun (b, baker, src, _) -> + let memo_size = 8 in + originate_contract + "contracts/sapling_contract_double.tz" + "(Pair { } { })" + src + b + baker + >>=? fun (dst, b, anti_replay) -> + let wa = wallet_gen () in + let hex_transac_1 = hex_shield ~memo_size wa anti_replay in + let wb = wallet_gen () in + let hex_transac_2 = hex_shield ~memo_size wb anti_replay in + let str_1 = + "(Pair True (Pair " ^ hex_transac_1 ^ " " ^ hex_transac_2 ^ "))" + in + let str_2 = + "(Pair False (Pair " ^ hex_transac_2 ^ " " ^ hex_transac_1 ^ "))" + in + (* transac 1 is applied to state_1*) + let parameters_1 = + Alpha_context.Script.(lazy_expr (expression_from_string str_1)) + in + (* tranasc_2 is applied to state_2*) + let parameters_2 = + Alpha_context.Script.(lazy_expr (expression_from_string str_2)) + in + let fee = Test_tez.Tez.of_int 10 in + Op.transaction + ~fee + (B b) + src + dst + Test_tez.Tez.zero + ~parameters:parameters_1 + >>=? fun operation -> + next_block b operation + >>=? fun b -> + Op.transaction + ~fee + (B b) + src + dst + Test_tez.Tez.zero + ~parameters:parameters_2 + >>=? fun operation -> + next_block b operation + >>=? fun b -> + Incremental.begin_construction b + >>=? fun incr -> + let ctx = Incremental.alpha_ctxt incr in + let ctx_without_gas = Alpha_context.Gas.set_unlimited ctx in + Alpha_services.Contract.storage Block.rpc_ctxt b dst + >>=? fun storage -> + let storage_lazy_expr = Alpha_context.Script.lazy_expr storage in + let tytype = + let memo_size = memo_size_of_int memo_size in + let open Script_typed_ir in + let state_ty = Sapling_state_t (memo_size, None) in + Pair_t ((state_ty, None, None), (state_ty, None, None), None) + in + Script_ir_translator.parse_storage + ctx_without_gas + ~legacy:true + ~allow_forged:true + tytype + ~storage:storage_lazy_expr + >>= wrap + >>=? fun ((state_1, state_2), _ctx) -> + (*Only works when diff is empty*) + let local_state_from_disk disk_state ctx = + let id = + Alpha_context.Sapling.(disk_state.id) + |> WithExceptions.Option.get ~loc:__LOC__ + in + Alpha_context.Sapling.get_diff + ctx + id + ~offset_commitment:0L + ~offset_nullifier:0L + () + >>= wrap + >|=? fun diff -> client_state_of_diff ~memo_size diff + in + local_state_from_disk state_1 ctx + >>=? fun state_1 -> + local_state_from_disk state_2 ctx + >|=? fun state_2 -> + (* we check that first state contains 15 to addr_1 but not 15 to addr_2*) + assert (Option.is_some @@ Tezos_sapling.Forge.Input.get state_1 0L wa.vk) ; + assert (Option.is_some @@ Tezos_sapling.Forge.Input.get state_2 0L wa.vk) ; + assert (Option.is_none @@ Tezos_sapling.Forge.Input.get state_1 0L wb.vk) ; + assert (Option.is_none @@ Tezos_sapling.Forge.Input.get state_2 0L wb.vk) + + let test_state_as_arg () = + init () + >>=? fun (b, baker, src, _) -> + originate_contract + "contracts/sapling_contract_state_as_arg.tz" + "None" + src + b + baker + >>=? fun (dst, b, anti_replay) -> + originate_contract "contracts/sapling_contract_send.tz" "Unit" src b baker + >>=? fun (dst_2, b, anti_replay_2) -> + let w = wallet_gen () in + let hex_transac_1 = hex_shield ~memo_size:8 w anti_replay in + let string = "Left " ^ hex_transac_1 in + let parameters = + Alpha_context.Script.(lazy_expr (expression_from_string string)) + in + let fee = Test_tez.Tez.of_int 10 in + Op.transaction ~fee (B b) src dst Test_tez.Tez.zero ~parameters + >>=? fun operation -> + next_block b operation + >>=? fun b -> + let contract = "0x" ^ to_hex dst Alpha_context.Contract.encoding in + let hex_transac_2 = hex_shield ~memo_size:8 w anti_replay_2 in + let string = "(Pair " ^ contract ^ " " ^ hex_transac_2 ^ ")" in + let parameters = + Alpha_context.Script.(lazy_expr (expression_from_string string)) + in + Op.transaction ~fee (B b) src dst_2 Test_tez.Tez.zero ~parameters + >>=? fun operation -> next_block b operation >>=? fun _b -> return_unit +end + +let tests = + [ Test_services.tztest + "commitments_add_uncommitted" + `Quick + Raw_context_tests.commitments_add_uncommitted; + Test_services.tztest + "nullifier_double" + `Quick + Raw_context_tests.nullifier_double; + Test_services.tztest + "nullifier_test" + `Quick + Raw_context_tests.nullifier_test; + Test_services.tztest + "cm_cipher_test" + `Quick + Raw_context_tests.cm_cipher_test; + Test_services.tztest + "list_insertion_test" + `Quick + Raw_context_tests.list_insertion_test; + Test_services.tztest "root" `Quick Raw_context_tests.root_test; + Test_services.tztest + "test_get_memo_size" + `Quick + Raw_context_tests.test_get_memo_size; + Test_services.tztest + "test_verify_memo" + `Quick + Alpha_context_tests.test_verify_memo; + Test_services.tztest + "test_bench_phases" + `Slow + Alpha_context_tests.test_bench_phases; + Test_services.tztest + "test_bench_fold_over_same_token" + `Slow + Alpha_context_tests.test_bench_fold_over_same_token; + Test_services.tztest + "test_double_spend_same_input" + `Quick + Alpha_context_tests.test_double_spend_same_input; + Test_services.tztest + "test_verifyupdate_one_transaction" + `Quick + Alpha_context_tests.test_verifyupdate_one_transaction; + Test_services.tztest + "test_verifyupdate_two_transactions" + `Quick + Alpha_context_tests.test_verifyupdate_two_transactions; + Test_services.tztest + "test_shielded_tez" + `Quick + Interpreter_tests.test_shielded_tez; + Test_services.tztest + "test use state from other contract and transact" + `Quick + Interpreter_tests.test_use_state_from_other_contract_and_transact; + Test_services.tztest + "Instruction PUSH sapling_state 0 should be forbidden" + `Quick + Interpreter_tests.test_push_sapling_state_should_be_forbidden; + Test_services.tztest + "test_transac_and_block" + `Quick + Interpreter_tests.test_transac_and_block; + Test_services.tztest "test_drop" `Quick Interpreter_tests.test_drop; + Test_services.tztest "test_double" `Quick Interpreter_tests.test_double; + Test_services.tztest + "test_state_as_arg" + `Quick + Interpreter_tests.test_state_as_arg ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_saturation.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_saturation.ml new file mode 100644 index 0000000000000000000000000000000000000000..33612ca9b8237df883d0f952432d358014c827e7 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_saturation.ml @@ -0,0 +1,191 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (saturated arithmetic) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe \ + -- test "^saturation arithmetic$" + Subject: The gas is represented using saturated arithmetic. + These unit tests check that saturated arithmetic operations + are correctly implemented. +*) + +open Protocol + +let valid (z : _ Saturation_repr.t) = + let x = z |> Saturation_repr.to_int in + x >= 0 && x < max_int + +exception Saturating_test_error of string + +let err x = Exn (Saturating_test_error x) + +let small_enough (z : _ Saturation_repr.t) = + Saturation_repr.(Compare.Int.((z |> to_int) land 0x7fffffff80000000 = 0)) + +let ok_int x = + match Saturation_repr.of_int_opt x with None -> assert false | Some x -> x + +let n = ok_int 123123 + +let m = ok_int 377337 + +let add () = + Saturation_repr.( + fail_unless + (add saturated (ok_int 1) = saturated) + (err "saturated + 1 <> saturated") + >>=? fun () -> + fail_unless (add zero n = n) (err "zero + n <> n") + >>=? fun () -> + fail_unless (add n zero = n) (err "n + zero <> n") + >>=? fun () -> + let r = add n m in + fail_unless + (valid r && r = ok_int ((n |> to_int) + (m |> to_int))) + (err "add does not behave like + on small numbers.")) + +let sub () = + Saturation_repr.( + fail_unless (sub zero n = zero) (err "zero - n <> zero") + >>=? fun () -> + let n = max n m and m = min n m in + let r = sub n m in + fail_unless + (valid r && r = ok_int ((n |> to_int) - (m |> to_int))) + (err "sub does not behave like - on small numbers.")) + +let mul_safe_of_int x = + Saturation_repr.( + match mul_safe (ok_int x) with Some x -> x | None -> assert false) + +let n' = mul_safe_of_int 1000 + +let m' = mul_safe_of_int 10000 + +let mul_fast () = + Saturation_repr.( + fail_unless (mul_fast zero n' = zero) (err "mul_fast zero x <> zero") + >>=? fun () -> + fail_unless (mul_fast n' zero = zero) (err "mul_fast x zero <> zero") + >>=? fun () -> + let r = mul_fast n' m' in + fail_unless + (valid r && r = ok_int ((n' |> to_int) * (m' |> to_int))) + (err "mul_fast does not behave like * on small numbers.")) + +let scale_fast () = + Saturation_repr.( + fail_unless (scale_fast zero n = zero) (err "scale_fast zero x <> zero") + >>=? fun () -> + fail_unless (scale_fast n' zero = zero) (err "scale_fast x zero <> zero") + >>=? fun () -> + fail_unless + (scale_fast n' saturated = saturated) + (err "scale_fast x saturated <> saturated") + >>=? fun () -> + let r = scale_fast n' m in + fail_unless + (valid r && r = ok_int ((n' |> to_int) * (m |> to_int))) + (err "mul_fast does not behave like * on small numbers.")) + +let mul () = + Saturation_repr.( + fail_unless + (mul saturated saturated = saturated) + (err "saturated * saturated <> saturated") + >>=? fun () -> + fail_unless (mul zero saturated = zero) (err "zero * saturated <> zero") + >>=? fun () -> + fail_unless (mul saturated zero = zero) (err "saturated * zero <> zero") + >>=? fun () -> + let max_squared = ok_int (1 lsl 31) in + let r = mul max_squared max_squared in + fail_unless (r = saturated) (err "2 ^ 31 * 2 ^ 31 should be saturated") + >>=? fun () -> + let safe_squared = ok_int ((1 lsl 31) - 1) in + let r = mul safe_squared safe_squared in + fail_unless + (valid r && r <> saturated) + (err "(2 ^ 31 - 1) * (2 ^ 31 - 1) should not be saturated") + >>=? fun () -> + let r = mul n m in + fail_unless + (valid r && r = ok_int ((n |> to_int) * (m |> to_int))) + (err "mul does not behave like * on small numbers.")) + +let of_z_opt () = + fail_unless + (Saturation_repr.(of_z_opt (Z.succ (Z.of_int max_int))) = None) + (err + "of_z_opt should saturate when given a z integer greater than max_int.") + >>=? fun () -> + fail_unless + (Saturation_repr.(of_z_opt (Z.pred Z.zero)) = None) + (err "of_z_opt should fail on a z negative integer.") + >>=? fun () -> + fail_unless + (Saturation_repr.(of_z_opt (Z.of_int min_int)) = None) + (err "of_z_opt should fail on a z negative integer.") + +let encoding encoder () = + let check_encode_decode x = + Data_encoding.Binary.( + match to_bytes encoder (ok_int x) with + | Error _ -> + fail (err (Printf.sprintf "Problem during binary encoding of %d" x)) + | Ok bytes -> ( + match of_bytes encoder bytes with + | Error _ -> + fail + (err (Printf.sprintf "Problem during binary decoding of %d" x)) + | Ok x' -> + fail_unless + (ok_int x = x') + (err + (Printf.sprintf + "decode (encode %d) = %d <> %d" + x + (x' :> int) + x)) )) + in + join_ep (List.map check_encode_decode [0; 7373737373; max_int - 1]) + +let tests = + [ Test_services.tztest "Addition" `Quick add; + Test_services.tztest "Subtraction" `Quick sub; + Test_services.tztest "Multiplication" `Quick mul; + Test_services.tztest "Multiplication (fast version)" `Quick mul_fast; + Test_services.tztest "Scale fast" `Quick scale_fast; + Test_services.tztest "Conversion from Z" `Quick of_z_opt; + Test_services.tztest + "Encoding through z" + `Quick + (encoding Saturation_repr.z_encoding); + Test_services.tztest + "Encoding through n" + `Quick + (encoding Saturation_repr.n_encoding) ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_script_gas.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_script_gas.ml new file mode 100644 index 0000000000000000000000000000000000000000..c0c46933e73ff46cf92d153fda87126e58dbae88 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_script_gas.ml @@ -0,0 +1,134 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Michelson serialization gas) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^script deserialize gas$" + Subject: Unit tests pertaining to the computation of serialization + and deserialization gas of Michelson terms. +*) + +open Protocol +module S = Saturation_repr + +module Tested_terms () = struct + open Micheline + + let string = String (0, "this is a test string") + + let int = Int (0, Z.of_string "133713371337133713371337") + + let bytes = Bytes (0, Bytes.of_string "this is a value of type Bytes.t") + + (* We're not going to typecheck; the chosen primitive does not matter. *) + let some_prim = Michelson_v1_primitives.D_Unit + + (* replace this by a proper prng if you feel like it *) + let next_seed seed = seed + 1 + + let rec dummy_but_large_term depth seed k = + if depth = 0 then + let kind = seed mod 3 in + if kind = 0 then k string else if kind = 1 then k int else k bytes + else + let seed1 = next_seed seed in + let seed2 = next_seed seed1 in + dummy_but_large_term (depth - 1) seed1 (fun term1 -> + dummy_but_large_term (depth - 1) seed2 (fun term2 -> + let kind = seed mod 2 in + if kind = 0 then k (Prim (0, some_prim, [term1; term2], [])) + else k (Seq (0, [term1; term2])))) + + let dummy_but_large_term ~depth ~seed = + dummy_but_large_term depth seed (fun x -> x) + + let ( % ) g f x = g (f x) + + let terms : Script_repr.lazy_expr list = + List.map (Script_repr.lazy_expr % Micheline.strip_locations) + @@ [ string; + int; + bytes; + dummy_but_large_term ~depth:1 ~seed:1; + dummy_but_large_term ~depth:5 ~seed:1; + dummy_but_large_term ~depth:10 ~seed:1; + dummy_but_large_term ~depth:15 ~seed:1 ] + + let bytes = + List.map + (Data_encoding.Binary.to_bytes_exn Script_repr.lazy_expr_encoding) + terms + + let lazy_terms : Script_repr.lazy_expr list = + try + List.map + (Data_encoding.Binary.of_bytes_exn Script_repr.lazy_expr_encoding) + bytes + with Data_encoding.Binary.Read_error err -> + Format.eprintf "%a@." Data_encoding.Binary.pp_read_error err ; + assert false + + let minimal_costs = List.map Script_repr.minimal_deserialize_cost lazy_terms + + let full_costs = + List.map + (fun lazy_term -> + match Script_repr.force_decode lazy_term with + | Error _ -> + assert false + | Ok (_term, cost) -> + cost) + lazy_terms + + let check_correctness () = + List.iter2_e + ~when_different_lengths: + (TzTrace.make @@ Exn (Failure "differently sized cost lists")) + (fun smin full -> + if S.(smin <= full) then ok_unit + else + generic_error + "Script_repr: inconsistent costs %a vs %a@." + S.pp + smin + S.pp + full) + minimal_costs + full_costs + + let check_correctness () = Lwt.return @@ check_correctness () +end + +let test_check_property () = + let module T = Tested_terms () in + T.check_correctness () + +let tests = + [ Test_services.tztest + "Script_repr.minimal_deserialize_cost is a lower bound for full \ + deserialization cost" + `Quick + test_check_property ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_seed.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_seed.ml new file mode 100644 index 0000000000000000000000000000000000000000..3f39eedf879fcffe68c16e8c627368e54ca97aee --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_seed.ml @@ -0,0 +1,296 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (seed) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^seed$" + Subject: - seed_nonce_hash included in some blocks + - revelation operation of seed_nonce that should correspond + to each seed_nonce_hash +*) + +open Protocol +open Test_tez + +(** Baking [blocks_per_commitment] blocks without a [seed_nonce_hash] + commitment fails with [Invalid_commitment]. *) +let test_no_commitment () = + Context.init 5 + >>=? fun (b, _) -> + Context.get_constants (B b) + >>=? fun {parametric = {blocks_per_commitment; _}; _} -> + let blocks_per_commitment = Int32.to_int blocks_per_commitment in + (* Bake normally until before the commitment *) + Block.bake_n (blocks_per_commitment - 2) b + >>=? fun b -> + (* Forge a block with empty commitment and apply it *) + Block.Forge.forge_header b + >>=? fun header -> + Block.Forge.set_seed_nonce_hash None header + |> Block.Forge.sign_header + >>=? fun header -> + Block.apply header b + >>= fun e -> + Assert.proto_error ~loc:__LOC__ e (function + | Apply.Invalid_commitment _ -> + true + | _ -> + false) + +let baking_reward ctxt (b : Block.t) = + let priority = b.header.protocol_data.contents.priority in + Block.get_endorsing_power b + >>=? fun endorsing_power -> + Context.get_baking_reward ctxt ~priority ~endorsing_power + +(** Choose a baker, denote it by id. In the first cycle, make id bake only once. + Check that: + - after id bakes with a commitment the bond is frozen and the reward + allocated + - when id reveals the nonce too early, there's an error + - when id reveals at the right time but the wrong value, there's an error + - when another baker reveals correctly, it receives the tip + - revealing twice produces an error + - after [preserved cycles] a committer that correctly revealed + receives back the bond and the reward. *) +let test_revelation_early_wrong_right_twice () = + let open Assert in + Context.init 5 + >>=? fun (b, _) -> + Context.get_constants (B b) + >>=? fun csts -> + let bond = csts.parametric.block_security_deposit in + let tip = csts.parametric.seed_nonce_revelation_tip in + let blocks_per_commitment = + Int32.to_int csts.parametric.blocks_per_commitment + in + let preserved_cycles = csts.parametric.preserved_cycles in + (* get the pkh of a baker *) + Block.get_next_baker b + >>=? fun (pkh, _, _) -> + let id = Alpha_context.Contract.implicit_contract pkh in + let policy = Block.Excluding [pkh] in + (* bake until commitment, excluding id *) + Block.bake_n ~policy (blocks_per_commitment - 2) b + >>=? fun b -> + Context.Contract.balance ~kind:Main (B b) id + >>=? fun bal_main -> + Context.Contract.balance ~kind:Deposit (B b) id + >>=? fun bal_deposit -> + Context.Contract.balance ~kind:Rewards (B b) id + >>=? fun bal_rewards -> + (* the baker [id] will include a seed_nonce commitment *) + Block.bake ~policy:(Block.By_account pkh) b + >>=? fun b -> + Context.get_level (B b) + >>?= fun level_commitment -> + Context.get_seed_nonce_hash (B b) + >>=? fun committed_hash -> + baking_reward (B b) b + >>=? fun reward -> + (* test that the bond was frozen and the reward allocated *) + balance_was_debited ~loc:__LOC__ (B b) id bal_main bond + >>=? fun () -> + balance_was_credited ~loc:__LOC__ (B b) id ~kind:Deposit bal_deposit bond + >>=? fun () -> + balance_was_credited ~loc:__LOC__ (B b) id ~kind:Rewards bal_rewards reward + >>=? fun () -> + (* test that revealing too early produces an error *) + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get committed_hash) + |> fun operation -> + Block.bake ~policy ~operation b + >>= fun e -> + let expected = function + | Nonce_storage.Too_early_revelation -> + true + | _ -> + false + in + Assert.proto_error ~loc:__LOC__ e expected + >>=? fun () -> + (* finish the cycle excluding the committing baker, id *) + Block.bake_until_cycle_end ~policy b + >>=? fun b -> + (* test that revealing at the right time but the wrong value produces an error *) + let (wrong_hash, _) = Nonce.generate () in + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get wrong_hash) + |> fun operation -> + Block.bake ~operation b + >>= fun e -> + Assert.proto_error ~loc:__LOC__ e (function + | Nonce_storage.Unexpected_nonce -> + true + | _ -> + false) + >>=? fun () -> + (* reveals correctly *) + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get committed_hash) + |> fun operation -> + Block.get_next_baker ~policy b + >>=? fun (baker_pkh, _, _) -> + let baker = Alpha_context.Contract.implicit_contract baker_pkh in + Context.Contract.balance ~kind:Main (B b) baker + >>=? fun baker_bal_main -> + Context.Contract.balance ~kind:Deposit (B b) baker + >>=? fun baker_bal_deposit -> + Context.Contract.balance ~kind:Rewards (B b) baker + >>=? fun baker_bal_rewards -> + (* bake the operation in a block *) + Block.bake ~policy ~operation b + >>=? fun b -> + baking_reward (B b) b + >>=? fun baker_reward -> + (* test that the baker gets the tip reward *) + balance_was_debited ~loc:__LOC__ (B b) baker ~kind:Main baker_bal_main bond + >>=? fun () -> + balance_was_credited + ~loc:__LOC__ + (B b) + baker + ~kind:Deposit + baker_bal_deposit + bond + >>=? fun () -> + Tez.( +? ) baker_reward tip + >>?= fun expected_rewards -> + balance_was_credited + ~loc:__LOC__ + (B b) + baker + ~kind:Rewards + baker_bal_rewards + expected_rewards + >>=? fun () -> + (* test that revealing twice produces an error *) + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get wrong_hash) + |> fun operation -> + Block.bake ~operation ~policy b + >>= fun e -> + Assert.proto_error ~loc:__LOC__ e (function + | Nonce_storage.Previously_revealed_nonce -> + true + | _ -> + false) + >>=? fun () -> + (* bake [preserved_cycles] cycles excluding [id] *) + List.fold_left_es + (fun b _ -> Block.bake_until_cycle_end ~policy b) + b + (1 -- preserved_cycles) + >>=? fun b -> + (* test that [id] receives back the bond and the reward *) + (* note that in order to have that new_bal = bal_main + reward, + id can only bake once; this is why we exclude id from all other bake ops. *) + balance_was_credited ~loc:__LOC__ (B b) id ~kind:Main bal_main reward + >>=? fun () -> + balance_is ~loc:__LOC__ (B b) id ~kind:Deposit Tez.zero + >>=? fun () -> balance_is ~loc:__LOC__ (B b) id ~kind:Rewards Tez.zero + +(** - a committer at cycle 0, which doesn't reveal at cycle 1, + at the end of the cycle 1 looses the bond and the reward + - revealing too late produces an error *) +let test_revelation_missing_and_late () = + let open Context in + let open Assert in + Context.init 5 + >>=? fun (b, _) -> + get_constants (B b) + >>=? fun csts -> + baking_reward (B b) b + >>=? fun reward -> + let blocks_per_commitment = + Int32.to_int csts.parametric.blocks_per_commitment + in + (* bake until commitment *) + Block.bake_n (blocks_per_commitment - 2) b + >>=? fun b -> + (* the next baker [id] will include a seed_nonce commitment *) + Block.get_next_baker b + >>=? fun (pkh, _, _) -> + let id = Alpha_context.Contract.implicit_contract pkh in + Block.bake b + >>=? fun b -> + Context.get_level (B b) + >>?= fun level_commitment -> + Context.get_seed_nonce_hash (B b) + >>=? fun committed_hash -> + Context.Contract.balance ~kind:Main (B b) id + >>=? fun bal_main -> + Context.Contract.balance ~kind:Deposit (B b) id + >>=? fun bal_deposit -> + Context.Contract.balance ~kind:Rewards (B b) id + >>=? fun bal_rewards -> + (* finish cycle 0 excluding the committing baker [id] *) + let policy = Block.Excluding [pkh] in + Block.bake_until_cycle_end ~policy b + >>=? fun b -> + (* finish cycle 1 excluding the committing baker [id] *) + Block.bake_until_cycle_end ~policy b + >>=? fun b -> + (* test that baker [id], which didn't reveal at cycle 1 like it was supposed to, + at the end of the cycle 1 looses the reward but not the bond *) + balance_is ~loc:__LOC__ (B b) id ~kind:Main bal_main + >>=? fun () -> + balance_is ~loc:__LOC__ (B b) id ~kind:Deposit bal_deposit + >>=? fun () -> + balance_was_debited ~loc:__LOC__ (B b) id ~kind:Rewards bal_rewards reward + >>=? fun () -> + (* test that revealing too late (after cycle 1) produces an error *) + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get committed_hash) + |> fun operation -> + Block.bake ~operation b + >>= fun e -> + Assert.proto_error ~loc:__LOC__ e (function + | Nonce_storage.Too_late_revelation -> + true + | _ -> + false) + +let tests = + [ Test_services.tztest "no commitment" `Quick test_no_commitment; + Test_services.tztest + "revelation_early_wrong_right_twice" + `Quick + test_revelation_early_wrong_right_twice; + Test_services.tztest + "revelation_missing_and_late" + `Quick + test_revelation_missing_and_late ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_storage.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..5d510ba6e660ff738c90a90d1eecabef518d7bc1 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_storage.ml @@ -0,0 +1,229 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Context Storage + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test storage + Subject: Test the correctnesss of debug message from storage_functor + *) + +open Protocol +open Storage_functors +open Storage_sigs + +module Int32 = struct + type t = int32 + + let encoding = Data_encoding.int32 + + module Index = struct + type t = int + + let path_length = 1 + + let to_path c l = string_of_int c :: l + + let of_path = function + | [] | _ :: _ :: _ -> + None + | [c] -> + int_of_string_opt c + + type 'a ipath = 'a * t + + let args = + Storage_description.One + { + rpc_arg = Environment.RPC_arg.int; + encoding = Data_encoding.int31; + compare = Compare.Int.compare; + } + end +end + +module Int64 = struct + type t = int64 + + let encoding = Data_encoding.int64 + + module Index = struct + type t = int64 + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function + | [] | _ :: _ :: _ -> + None + | [c] -> + Int64.of_string_opt c + + type 'a ipath = 'a * t + + let args = + Storage_description.One + { + rpc_arg = Environment.RPC_arg.int64; + encoding = Data_encoding.int64; + compare = Compare.Int64.compare; + } + end +end + +let create_context name : (module Raw_context.T with type t = Raw_context.t) = + ( module Make_subcontext (Registered) (Raw_context) + (struct + let name = [name] + end) ) + +let create_subcontext name + (module Context : Raw_context.T with type t = Raw_context.t) : + (module Raw_context.T with type t = Raw_context.t) = + ( module Make_subcontext (Registered) (Context) + (struct + let name = [name] + end) ) + +let create_single_data_storage name + (module Context : Raw_context.T with type t = Raw_context.t) : + (module Single_data_storage + with type t = Context.t + and type value = Int32.t) = + ( module Make_single_data_storage (Registered) (Context) + (struct + let name = [name] + end) + (Int32) ) + +let create_indexed_subcontext_int32 + (module Context : Raw_context.T with type t = Raw_context.t) : + (module Data_set_storage with type t = Raw_context.t) = + (module Make_data_set_storage (Context) (Int32.Index)) + +let create_indexed_subcontext_int64 + (module Context : Raw_context.T with type t = Raw_context.t) : + (module Data_set_storage with type t = Raw_context.t) = + (module Make_data_set_storage (Context) (Int64.Index)) + +let must_failwith f_prog error = + try + let _ = f_prog () in + Alcotest.fail "Unexpected successful result" + with exc -> + if exc = error then Lwt.return_unit + else Alcotest.fail "Unexpected error result" + +(** Test: + + This test check that creating value where value already exists + fails*) +let test_register_single_data () = + let f_prog () = + let context = create_context "context1" in + let _single_data = create_single_data_storage "single_data" context in + create_single_data_storage "single_data" context + in + let error = + Invalid_argument + "Could not register a value at [context1 / single_data] because of an \ + existing Value." + in + must_failwith f_prog error + +(** Test: + + This test check that creating a subcontext where a value already exists + fails*) +let test_register_named_subcontext () = + let f_prog () = + let context = create_context "context2" in + let subcontext = create_subcontext "sub_context" context in + let _single_data = + create_single_data_storage "error_register" subcontext + in + let subcontext = create_subcontext "error_register" subcontext in + create_single_data_storage "single_data2" subcontext + in + let error = + Invalid_argument + "Could not register a named subcontext at [context2 / sub_context / \ + error_register] because of an existing Value." + in + must_failwith f_prog error + +(** Test: + + This test check that creating a indexed subcontext where a value already + exists fails*) +let test_register_indexed_subcontext () = + let f_prog () = + let context = create_context "context3" in + let _ = create_single_data_storage "single_value" context in + create_indexed_subcontext_int32 context + in + let error = + Invalid_argument + "Could not register an indexed subcontext at [context3] because of an \ + existing \n\ + single_value Value." + in + must_failwith f_prog error + +(** Test: + + This test check that creating a indexed subcontext where an indexed + subcontext already exists fails*) +let test_register_indexed_subcontext_2 () = + let f_prog () = + let context = create_context "context4" in + let _ = create_indexed_subcontext_int32 context in + create_indexed_subcontext_int64 context + in + let error = + Invalid_argument + "An indexed subcontext at [context4] already exists but has a different \ + argument: `int64` <> `int`." + in + must_failwith f_prog error + +let tests = + [ Alcotest_lwt.test_case + "register single data in existing path" + `Quick + (fun _ -> test_register_single_data); + Alcotest_lwt.test_case + "register named subcontext in existing path" + `Quick + (fun _ -> test_register_named_subcontext); + Alcotest_lwt.test_case + "register indexed subcontext in existing path" + `Quick + (fun _ -> test_register_indexed_subcontext); + Alcotest_lwt.test_case + "register indexed subcontext with existing indexed subcontext" + `Quick + (fun _ -> test_register_indexed_subcontext_2) ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_transfer.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_transfer.ml new file mode 100644 index 0000000000000000000000000000000000000000..992c70f63b01fdcdec86b179d8989e219d9465ac --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_transfer.ml @@ -0,0 +1,747 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (transfer) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^transfer$" + Subject: Quantities transfer between contracts. +*) + +open Protocol +open Alpha_context +open Test_tez + +(*********************************************************************) +(* Utility functions *) +(*********************************************************************) + +(** + [transfer_and_check_balances b fee src dst amount] + this function takes a block, an optional parameter fee if fee does not + given it will be set to zero tez, a source contract, a destination contract + and the amount that one wants to transfer. + + 1- Transfer the amount of tez (w/wo fee) from a source contract to a + destination contract. + + 2- Check the equivalent of the balance of the source/destination + contract before and after transfer is validated. + + This function returns a pair: + - A block that added a valid operation + - a valid operation *) +let transfer_and_check_balances ?(with_burn = false) ~loc b ?(fee = Tez.zero) + ?expect_failure src dst amount = + Tez.( +? ) fee amount + >>?= fun amount_fee -> + Context.Contract.balance (I b) src + >>=? fun bal_src -> + Context.Contract.balance (I b) dst + >>=? fun bal_dst -> + Op.transaction (I b) ~fee src dst amount + >>=? fun op -> + Incremental.add_operation ?expect_failure b op + >>=? fun b -> + Context.get_constants (I b) + >>=? fun {parametric = {origination_size; cost_per_byte; _}; _} -> + Tez.(cost_per_byte *? Int64.of_int origination_size) + >>?= fun origination_burn -> + let amount_fee_maybe_burn = + if with_burn then + match Tez.(amount_fee +? origination_burn) with + | Ok r -> + r + | Error _ -> + assert false + else amount_fee + in + Assert.balance_was_debited ~loc (I b) src bal_src amount_fee_maybe_burn + >>=? fun () -> + Assert.balance_was_credited ~loc (I b) dst bal_dst amount + >|=? fun () -> (b, op) + +(** + [transfer_to_itself_and_check_balances b fee contract amount] + this function takes a block, an optional parameter fee, + a contract that is a source and a destination contract, + and an amount of tez that one wants to transfer. + + 1- Transfer the amount of tez (w/wo transfer fee) from/to a contract itself. + + 2- Check the equivalent of the balance of the contract before + and after transfer. + + This function returns a pair: + - a block that added the valid transaction + - an valid transaction *) +let transfer_to_itself_and_check_balances ~loc b ?(fee = Tez.zero) contract + amount = + Context.Contract.balance (I b) contract + >>=? fun bal -> + Op.transaction (I b) ~fee contract contract amount + >>=? fun op -> + Incremental.add_operation b op + >>=? fun b -> + Assert.balance_was_debited ~loc (I b) contract bal fee >|=? fun () -> (b, op) + +(** + [n_transactions n b fee source dest amount] + this function takes a number of "n" that one wish to transfer, + a block, an optional parameter fee, a source contract, + a destination contract and an amount one wants to transfer. + + This function will do a transaction from a source contract to + a destination contract with the amount "n" times. *) +let n_transactions n b ?fee source dest amount = + List.fold_left_es + (fun b _ -> + transfer_and_check_balances ~loc:__LOC__ b ?fee source dest amount + >|=? fun (b, _) -> b) + b + (1 -- n) + +let ten_tez = Tez.of_int 10 + +(*********************************************************************) +(* Tests *) +(*********************************************************************) + +let register_two_contracts () = + Context.init 2 + >|=? function + | (_, []) | (_, [_]) -> + assert false + | (b, contract_1 :: contract_2 :: _) -> + (b, contract_1, contract_2) + +(** Compute a fraction of 2/[n] of the balance of [contract] *) +let two_over_n_of_balance incr contract n = + Context.Contract.balance (I incr) contract + >>=? fun balance -> + Lwt.return (Tez.( /? ) balance n >>? fun res -> Tez.( *? ) res 2L) + +(********************) +(** Single transfer *) + +(********************) + +let single_transfer ?fee ?expect_failure amount = + register_two_contracts () + >>=? fun (b, contract_1, contract_2) -> + Incremental.begin_construction b + >>=? fun b -> + transfer_and_check_balances + ~loc:__LOC__ + ?fee + ?expect_failure + b + contract_1 + contract_2 + amount + >>=? fun (b, _) -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(** Single transfer without fee. *) +let test_block_with_a_single_transfer () = single_transfer Tez.one + +(** Single transfer with fee. *) +let test_block_with_a_single_transfer_with_fee () = + single_transfer ~fee:Tez.one Tez.one + +(** Single transfer without fee. *) +let test_transfer_zero_tez () = + single_transfer + ~expect_failure:(function + | Environment.Ecoproto_error (Contract_storage.Empty_transaction _) :: _ + -> + return_unit + | _ -> + failwith "Empty transaction should fail") + Tez.zero + +(** Transfer zero tez from an implicit contract. *) +let test_transfer_zero_implicit () = + Context.init 1 + >>=? fun (b, contracts) -> + let dest = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 in + let account = Account.new_account () in + Incremental.begin_construction b + >>=? fun i -> + let src = Contract.implicit_contract account.Account.pkh in + Op.transaction (I i) src dest Tez.zero + >>=? fun op -> + Incremental.add_operation i op + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Contract_storage.Empty_implicit_contract _ -> + true + | _ -> + false) + +(** Transfer to originated contract. *) +let test_transfer_to_originate_with_fee () = + Context.init 1 + >>=? fun (b, contracts) -> + let contract = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 + in + Incremental.begin_construction b + >>=? fun b -> + two_over_n_of_balance b contract 10L + >>=? fun fee -> + (* originated contract, paying a fee to originated this contract *) + Op.origination (I b) ~fee:ten_tez contract ~script:Op.dummy_script + >>=? fun (operation, new_contract) -> + Incremental.add_operation b operation + >>=? fun b -> + two_over_n_of_balance b contract 3L + >>=? fun amount -> + transfer_and_check_balances ~loc:__LOC__ b ~fee contract new_contract amount + >>=? fun (b, _) -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(** Transfer from balance. *) +let test_transfer_amount_of_contract_balance () = + register_two_contracts () + >>=? fun (b, contract_1, contract_2) -> + Context.Contract.pkh contract_1 + >>=? fun pkh1 -> + (* given that contract_1 no longer has a sufficient balance to bake, + make sure it cannot be chosen as baker *) + Incremental.begin_construction b ~policy:(Block.Excluding [pkh1]) + >>=? fun b -> + (* get the balance of the source contract *) + Context.Contract.balance (I b) contract_1 + >>=? fun balance -> + (* transfer all the tez inside contract 1 *) + transfer_and_check_balances ~loc:__LOC__ b contract_1 contract_2 balance + >>=? fun (b, _) -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(** Transfer to oneself. *) +let test_transfers_to_self () = + Context.init 1 + >>=? fun (b, contracts) -> + let contract = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 + in + Incremental.begin_construction b + >>=? fun b -> + two_over_n_of_balance b contract 3L + >>=? fun amount -> + transfer_to_itself_and_check_balances ~loc:__LOC__ b contract amount + >>=? fun (b, _) -> + two_over_n_of_balance b contract 5L + >>=? fun fee -> + transfer_to_itself_and_check_balances ~loc:__LOC__ b ~fee contract ten_tez + >>=? fun (b, _) -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(** Forgot to add the valid transaction into the block. *) +let test_missing_transaction () = + register_two_contracts () + >>=? fun (b, contract_1, contract_2) -> + (* given that contract_1 no longer has a sufficient balance to bake, + make sure it cannot be chosen as baker *) + Context.Contract.pkh contract_1 + >>=? fun pkh1 -> + Incremental.begin_construction b ~policy:(Block.Excluding [pkh1]) + >>=? fun b -> + two_over_n_of_balance b contract_1 6L + >>=? fun amount -> + (* Do the transfer 3 times from source contract to destination contract *) + n_transactions 3 b contract_1 contract_2 amount + >>=? fun b -> + (* do the fourth transfer from source contract to destination contract *) + Op.transaction (I b) contract_1 contract_2 amount + >>=? fun _ -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(********************) +(* The following tests are for different kind of contracts: + - implicit to implicit + - implicit to originated + - originated to implicit + - originated to originated *) + +(********************) + +(** Implicit to Implicit. *) +let test_transfer_from_implicit_to_implicit_contract () = + Context.init 1 + >>=? fun (b, contracts) -> + let bootstrap_contract = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 + in + let account_a = Account.new_account () in + let account_b = Account.new_account () in + Incremental.begin_construction b + >>=? fun b -> + let src = Contract.implicit_contract account_a.Account.pkh in + two_over_n_of_balance b bootstrap_contract 3L + >>=? fun amount1 -> + two_over_n_of_balance b bootstrap_contract 10L + >>=? fun fee1 -> + transfer_and_check_balances + ~with_burn:true + ~loc:__LOC__ + ~fee:fee1 + b + bootstrap_contract + src + amount1 + >>=? fun (b, _) -> + (* Create an implicit contract as a destination contract. *) + let dest = Contract.implicit_contract account_b.pkh in + two_over_n_of_balance b bootstrap_contract 4L + >>=? fun amount2 -> + two_over_n_of_balance b bootstrap_contract 10L + >>=? fun fee2 -> + (* Transfer from implicit contract to another implicit contract. *) + transfer_and_check_balances + ~with_burn:true + ~loc:__LOC__ + ~fee:fee2 + b + src + dest + amount2 + >>=? fun (b, _) -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(** Implicit to originated. *) +let test_transfer_from_implicit_to_originated_contract () = + Context.init 1 + >>=? fun (b, contracts) -> + let bootstrap_contract = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 + in + let contract = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 + in + let account = Account.new_account () in + let src = Contract.implicit_contract account.Account.pkh in + Incremental.begin_construction b + >>=? fun b -> + two_over_n_of_balance b bootstrap_contract 3L + >>=? fun amount1 -> + (* transfer the money to implicit contract *) + transfer_and_check_balances + ~with_burn:true + ~loc:__LOC__ + b + bootstrap_contract + src + amount1 + >>=? fun (b, _) -> + (* originated contract *) + Op.origination (I b) contract ~script:Op.dummy_script + >>=? fun (operation, new_contract) -> + Incremental.add_operation b operation + >>=? fun b -> + two_over_n_of_balance b bootstrap_contract 4L + >>=? fun amount2 -> + (* transfer from implicit contract to originated contract *) + transfer_and_check_balances ~loc:__LOC__ b src new_contract amount2 + >>=? fun (b, _) -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(********************) +(* Slow tests case *) + +(********************) + +let multiple_transfer n ?fee amount = + register_two_contracts () + >>=? fun (b, contract_1, contract_2) -> + Incremental.begin_construction b + >>=? fun b -> + n_transactions n b ?fee contract_1 contract_2 amount + >>=? fun b -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(** 1- Create a block with two contracts; + 2- Apply 100 transfers. +*) +let test_block_with_multiple_transfers () = + multiple_transfer 99 (Tez.of_int 1000) + +(** 1- Create a block with two contracts; + 2- Apply 100 transfers with 10tz fee. *) +let test_block_with_multiple_transfers_pay_fee () = + multiple_transfer 10 ~fee:ten_tez (Tez.of_int 1000) + +(* TODO : increase the number of operations and add a `Slow tag to it in `tests` *) + +(** 1- Create a block with 8 contracts; + 2- Apply multiple transfers without fees; + 3- Apply multiple transfers with fees. *) +let test_block_with_multiple_transfers_with_without_fee () = + Context.init 8 + >>=? fun (b, contracts) -> + let contracts = Array.of_list contracts in + Incremental.begin_construction b + >>=? fun b -> + let hundred = Tez.of_int 100 in + let ten = Tez.of_int 10 in + let twenty = Tez.of_int 20 in + n_transactions 10 b contracts.(0) contracts.(1) Tez.one + >>=? fun b -> + n_transactions 30 b contracts.(1) contracts.(2) hundred + >>=? fun b -> + n_transactions 30 b contracts.(1) contracts.(3) hundred + >>=? fun b -> + n_transactions 30 b contracts.(4) contracts.(3) hundred + >>=? fun b -> + n_transactions 20 b contracts.(0) contracts.(1) hundred + >>=? fun b -> + n_transactions 10 b contracts.(1) contracts.(3) hundred + >>=? fun b -> + n_transactions 10 b contracts.(1) contracts.(3) hundred + >>=? fun b -> + n_transactions 20 ~fee:ten b contracts.(3) contracts.(4) ten + >>=? fun b -> + n_transactions 10 ~fee:twenty b contracts.(4) contracts.(5) ten + >>=? fun b -> + n_transactions 70 ~fee:twenty b contracts.(6) contracts.(0) twenty + >>=? fun b -> + n_transactions 550 ~fee:twenty b contracts.(6) contracts.(4) twenty + >>=? fun b -> + n_transactions 50 ~fee:ten b contracts.(7) contracts.(5) twenty + >>=? fun b -> + n_transactions 30 ~fee:ten b contracts.(0) contracts.(7) hundred + >>=? fun b -> + n_transactions 20 ~fee:ten b contracts.(1) contracts.(0) twenty + >>=? fun b -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(** Build a chain that has 10 blocks. *) +let test_build_a_chain () = + register_two_contracts () + >>=? fun (b, contract_1, contract_2) -> + let ten = Tez.of_int 10 in + List.fold_left_es + (fun b _ -> + Incremental.begin_construction b + >>=? fun b -> + transfer_and_check_balances ~loc:__LOC__ b contract_1 contract_2 ten + >>=? fun (b, _) -> Incremental.finalize_block b) + b + (1 -- 10) + >>=? fun _ -> return_unit + +(*********************************************************************) +(* Expected error test cases *) +(*********************************************************************) + +(** Transferring zero tez is forbidden in implicit contract. *) +let test_empty_implicit () = + Context.init 1 + >>=? fun (b, contracts) -> + let dest = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 in + let account = Account.new_account () in + Incremental.begin_construction b + >>=? fun incr -> + let src = Contract.implicit_contract account.Account.pkh in + two_over_n_of_balance incr dest 3L + >>=? fun amount -> + (* Transfer zero tez from an implicit contract. *) + Op.transaction (I incr) src dest amount + >>=? fun op -> + Incremental.add_operation incr op + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Contract_storage.Empty_implicit_contract _ -> + true + | _ -> + false) + +(** Balance is too low to transfer. *) +let test_balance_too_low fee () = + register_two_contracts () + >>=? fun (b, contract_1, contract_2) -> + Incremental.begin_construction b + >>=? fun i -> + Context.Contract.balance (I i) contract_1 + >>=? fun balance1 -> + Context.Contract.balance (I i) contract_2 + >>=? fun balance2 -> + (* transfer the amount of tez that is bigger than the balance in the source contract *) + Op.transaction ~fee (I i) contract_1 contract_2 Tez.max_tez + >>=? fun op -> + let expect_failure = function + | Environment.Ecoproto_error (Contract_storage.Balance_too_low _) :: _ -> + return_unit + | _ -> + failwith "balance too low should fail" + in + (* the fee is higher than the balance then raise an error "Balance_too_low" *) + if fee > balance1 then + Incremental.add_operation ~expect_failure i op >>= fun _res -> return_unit + (* the fee is smaller than the balance, then the transfer is accepted + but it is not processed, and fees are taken *) + else + Incremental.add_operation ~expect_failure i op + >>=? fun i -> + (* contract_1 loses the fees *) + Assert.balance_was_debited ~loc:__LOC__ (I i) contract_1 balance1 fee + >>=? fun () -> + (* contract_2 is not credited *) + Assert.balance_was_credited ~loc:__LOC__ (I i) contract_2 balance2 Tez.zero + +(** 1- Create a block, and three contracts; + 2- Add a transfer that at the end the balance of a contract is + zero into this block; + 3- Add another transfer that send tez from a zero balance contract; + 4- Catch the expected error: Balance_too_low. *) +let test_balance_too_low_two_transfers fee () = + Context.init 3 + >>=? fun (b, contracts) -> + let contract_1 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 + in + let contract_2 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 1 + in + let contract_3 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 2 + in + Incremental.begin_construction b + >>=? fun i -> + Context.Contract.balance (I i) contract_1 + >>=? fun balance -> + Tez.( /? ) balance 3L + >>?= fun res -> + Tez.( *? ) res 2L + >>?= fun two_third_of_balance -> + transfer_and_check_balances + ~loc:__LOC__ + i + contract_1 + contract_2 + two_third_of_balance + >>=? fun (i, _) -> + Context.Contract.balance (I i) contract_1 + >>=? fun balance1 -> + Context.Contract.balance (I i) contract_3 + >>=? fun balance3 -> + Op.transaction ~fee (I i) contract_1 contract_3 two_third_of_balance + >>=? fun operation -> + let expect_failure = function + | Environment.Ecoproto_error (Contract_storage.Balance_too_low _) :: _ -> + return_unit + | _ -> + failwith "balance too low should fail" + in + Incremental.add_operation ~expect_failure i operation + >>=? fun i -> + (* contract_1 loses the fees *) + Assert.balance_was_debited ~loc:__LOC__ (I i) contract_1 balance1 fee + >>=? fun () -> + (* contract_3 is not credited *) + Assert.balance_was_credited ~loc:__LOC__ (I i) contract_3 balance3 Tez.zero + +(** The counter is already used for the previous operation. *) +let invalid_counter () = + register_two_contracts () + >>=? fun (b, contract_1, contract_2) -> + Incremental.begin_construction b + >>=? fun b -> + Op.transaction (I b) contract_1 contract_2 Tez.one + >>=? fun op1 -> + Op.transaction (I b) contract_1 contract_2 Tez.one + >>=? fun op2 -> + Incremental.add_operation b op1 + >>=? fun b -> + Incremental.add_operation b op2 + >>= fun b -> + Assert.proto_error ~loc:__LOC__ b (function + | Contract_storage.Counter_in_the_past _ -> + true + | _ -> + false) + +(** Same as before but through a different way to perform this + error. *) +let test_add_the_same_operation_twice () = + register_two_contracts () + >>=? fun (b, contract_1, contract_2) -> + Incremental.begin_construction b + >>=? fun b -> + transfer_and_check_balances ~loc:__LOC__ b contract_1 contract_2 ten_tez + >>=? fun (b, op_transfer) -> + Op.transaction (I b) contract_1 contract_2 ten_tez + >>=? fun _ -> + Incremental.add_operation b op_transfer + >>= fun b -> + Assert.proto_error ~loc:__LOC__ b (function + | Contract_storage.Counter_in_the_past _ -> + true + | _ -> + false) + +(** Check ownership. *) +let test_ownership_sender () = + register_two_contracts () + >>=? fun (b, contract_1, contract_2) -> + Incremental.begin_construction b + >>=? fun b -> + (* get the manager of the contract_1 as a sender *) + Context.Contract.manager (I b) contract_1 + >>=? fun manager -> + (* create an implicit_contract *) + let imcontract_1 = Alpha_context.Contract.implicit_contract manager.pkh in + transfer_and_check_balances ~loc:__LOC__ b imcontract_1 contract_2 Tez.one + >>=? fun (b, _) -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(*********************************************************************) +(* Random transfer *) + +(* Return a pair of minimum and maximum random number. *) +let random_range (min, max) = + let interv = max - min + 1 in + let init = + Random.self_init () ; + Random.int interv + min + in + init + +(* Return a random contract. *) +let random_contract contract_array = + let i = Random.int (Array.length contract_array) in + contract_array.(i) + +(** Transfer by randomly choose amount 10 contracts, and randomly + choose the amount in the source contract. *) +let test_random_transfer () = + Context.init 10 + >>=? fun (b, contracts) -> + let contracts = Array.of_list contracts in + let source = random_contract contracts in + let dest = random_contract contracts in + Context.Contract.pkh source + >>=? fun source_pkh -> + (* given that source may not have a sufficient balance for the transfer + to bake, + make sure it cannot be chosen as baker *) + Incremental.begin_construction b ~policy:(Block.Excluding [source_pkh]) + >>=? fun b -> + Context.Contract.balance (I b) source + >>=? fun amount -> + ( if source = dest then + transfer_to_itself_and_check_balances ~loc:__LOC__ b source amount + else transfer_and_check_balances ~loc:__LOC__ b source dest amount ) + >>=? fun (b, _) -> Incremental.finalize_block b >>=? fun _ -> return_unit + +(** Transfer random transactions. *) +let test_random_multi_transactions () = + let n = random_range (1, 100) in + multiple_transfer n (Tez.of_int 100) + +(*********************************************************************) + +let tests = + [ (* single transfer *) + Test_services.tztest + "single transfer" + `Quick + test_block_with_a_single_transfer; + Test_services.tztest + "single transfer with fee" + `Quick + test_block_with_a_single_transfer_with_fee; + (* transfer zero tez *) + Test_services.tztest + "single transfer zero tez" + `Quick + test_transfer_zero_tez; + Test_services.tztest + "transfer zero tez from implicit contract" + `Quick + test_transfer_zero_implicit; + (* transfer to originated contract *) + Test_services.tztest + "transfer to originated contract paying transaction fee" + `Quick + test_transfer_to_originate_with_fee; + (* transfer by the balance of contract *) + Test_services.tztest + "transfer the amount from source contract balance" + `Quick + test_transfer_amount_of_contract_balance; + (* transfer to itself *) + Test_services.tztest "transfers to itself" `Quick test_transfers_to_self; + (* missing operation *) + Test_services.tztest "missing transaction" `Quick test_missing_transaction; + (* transfer from/to implicit/originated contracts*) + Test_services.tztest + "transfer from an implicit to implicit contract " + `Quick + test_transfer_from_implicit_to_implicit_contract; + Test_services.tztest + "transfer from an implicit to an originated contract" + `Quick + test_transfer_from_implicit_to_originated_contract; + (* Slow tests *) + Test_services.tztest + "block with multiple transfers" + `Slow + test_block_with_multiple_transfers; + (* TODO increase the number of transaction times *) + Test_services.tztest + "block with multiple transfer paying fee" + `Slow + test_block_with_multiple_transfers_pay_fee; + Test_services.tztest + "block with multiple transfer without paying fee" + `Slow + test_block_with_multiple_transfers_with_without_fee; + (* build the chain *) + Test_services.tztest "build a chain" `Quick test_build_a_chain; + (* Erroneous *) + Test_services.tztest "empty implicit" `Quick test_empty_implicit; + Test_services.tztest + "balance too low - transfer zero" + `Quick + (test_balance_too_low Tez.zero); + Test_services.tztest + "balance too low" + `Quick + (test_balance_too_low Tez.one); + Test_services.tztest + "balance too low (max fee)" + `Quick + (test_balance_too_low Tez.max_tez); + Test_services.tztest + "balance too low with two transfers - transfer zero" + `Quick + (test_balance_too_low_two_transfers Tez.zero); + Test_services.tztest + "balance too low with two transfers" + `Quick + (test_balance_too_low_two_transfers Tez.one); + Test_services.tztest "invalid_counter" `Quick invalid_counter; + Test_services.tztest + "add the same operation twice" + `Quick + test_add_the_same_operation_twice; + Test_services.tztest "ownership sender" `Quick test_ownership_sender; + (* Random tests *) + Test_services.tztest "random transfer" `Quick test_random_transfer; + Test_services.tztest + "random multi transfer" + `Quick + test_random_multi_transactions ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_typechecking.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_typechecking.ml new file mode 100644 index 0000000000000000000000000000000000000000..d59c4d322611d346da1b58a8636990c90f81fec3 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_typechecking.ml @@ -0,0 +1,830 @@ +(** Testing + ------- + Component: Protocol (type-checking) + Invocation: cd src/proto_alpha/lib_protocol/test + dune exec ./main.exe -- test "^typechecking$" + Subject: Type-checking +*) + +open Protocol +open Alpha_context +open Script_interpreter +open Micheline + +exception Expression_from_string + +let expression_from_string str : Script.expr tzresult Lwt.t = + let (ast, errs) = Michelson_v1_parser.parse_expression ~check:false str in + ( match errs with + | [] -> + () + | lst -> + Format.printf "expr_from_string: %a\n" Error_monad.pp_print_error lst ; + raise Expression_from_string ) ; + return ast.expanded + +let ( >>=?? ) x y = + x + >>= function + | Ok s -> + y s + | Error err -> + Lwt.return @@ Error (Environment.wrap_tztrace err) + +let wrap_error_lwt x = x >>= fun x -> Lwt.return @@ Environment.wrap_tzresult x + +let test_context () = + Context.init 3 + >>=? fun (b, _cs) -> + Incremental.begin_construction b + >>=? fun v -> return (Incremental.alpha_ctxt v) + +let test_context_with_nat_nat_big_map () = + Context.init 3 + >>=? fun (b, contracts) -> + let source = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd contracts in + Op.origination (B b) source ~script:Op.dummy_script + >>=? fun (operation, originated) -> + Block.bake ~operation b + >>=? fun b -> + Incremental.begin_construction b + >>=? fun v -> + let ctxt = Incremental.alpha_ctxt v in + wrap_error_lwt @@ Big_map.fresh ~temporary:false ctxt + >>=? fun (ctxt, id) -> + let nat_ty = Script_typed_ir.Nat_t None in + wrap_error_lwt @@ Lwt.return @@ Script_ir_translator.unparse_ty ctxt nat_ty + >>=? fun (nat_ty_node, ctxt) -> + let nat_ty_expr = Micheline.strip_locations nat_ty_node in + let alloc = Big_map.{key_type = nat_ty_expr; value_type = nat_ty_expr} in + let init = Lazy_storage.Alloc alloc in + let diffs = + [ Lazy_storage.make + Lazy_storage.Kind.Big_map + id + (Update {init; updates = []}) ] + in + wrap_error_lwt + @@ Contract.update_script_storage ctxt originated nat_ty_expr (Some diffs) + >>=? fun ctxt -> return (ctxt, id) + +let default_source = Contract.implicit_contract Signature.Public_key_hash.zero + +let default_step_constants = + { + source = default_source; + payer = default_source; + self = default_source; + amount = Tez.zero; + chain_id = Chain_id.zero; + } + +(** Helper function that parses and types a script, its initial storage and + parameters from strings. It then executes the typed script with the storage + and parameter and returns the result. *) +let run_script ctx ?(step_constants = default_step_constants) contract + ?(entrypoint = "default") ~storage ~parameter () = + expression_from_string contract + >>=? fun contract_expr -> + expression_from_string storage + >>=? fun storage_expr -> + expression_from_string parameter + >>=? fun parameter_expr -> + let script = + Script.{code = lazy_expr contract_expr; storage = lazy_expr storage_expr} + in + Script_interpreter.execute + ctx + Readable + step_constants + ~script + ~entrypoint + ~parameter:parameter_expr + ~internal:false + >>=?? fun res -> return res + +let read_file filename = + let ch = open_in filename in + let s = really_input_string ch (in_channel_length ch) in + close_in ch ; s + +(** Check that the custom stack overflow exception is triggered when + it should be. *) +let test_typecheck_stack_overflow () = + test_context () + >>=? fun ctxt -> + let storage = "Unit" in + let parameter = "Unit" in + let script = read_file "./contracts/big_interpreter_stack.tz" in + run_script ctxt script ~storage ~parameter () + >>= function + | Ok _ -> + Alcotest.fail "expected an error" + | Error lst + when List.mem + (Environment.Ecoproto_error + Script_tc_errors.Typechecking_too_many_recursive_calls) + lst -> + return () + | Error errs -> + Alcotest.failf "Unexpected error: %a" Error_monad.pp_print_error errs + +(* NOTE: this test fails with an out-of-memory exception. *) +let _test_unparse_stack_overflow () = + test_context () + >>=? fun ctxt -> + (* Meme *) + let enorme_et_seq n = + let rec aux n acc = aux (n - 1) @@ Micheline.Seq (0, [acc]) in + aux n (Micheline.Int (0, Z.zero)) + in + Script_ir_translator.(unparse_code ctxt Readable (enorme_et_seq 10_001)) + >>= function + | Ok _ -> + Alcotest.fail "expected an error" + | Error trace -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + let expect_id = "michelson_v1.unparsing_stack_overflow" in + let expect_descrfiption = + "Too many recursive calls were needed for unparsing" + in + if + Astring.String.is_infix ~affix:expect_id trace_string + && Astring.String.is_infix ~affix:expect_descrfiption trace_string + then return_unit + else + Alcotest.failf + "Unexpected error (%s) at %s" + trace_string + __LOC__ + return_unit + +let location = function + | Prim (loc, _, _, _) + | Int (loc, _) + | String (loc, _) + | Bytes (loc, _) + | Seq (loc, _) -> + loc + +let test_parse_ty ctxt node expected = + let legacy = false in + let allow_lazy_storage = true in + let allow_operation = true in + let allow_contract = true in + let allow_ticket = true in + Environment.wrap_tzresult + ( Script_ir_translator.parse_ty + ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + node + >>? fun (Script_ir_translator.Ex_ty actual, ctxt) -> + Script_ir_translator.ty_eq ctxt (location node) actual expected + >|? fun (_, ctxt) -> ctxt ) + +let test_parse_comb_type () = + let open Script in + let open Script_typed_ir in + let nat_prim = Prim (-1, T_nat, [], []) in + let nat_prim_a = Prim (-1, T_nat, [], ["%a"]) in + let nat_prim_b = Prim (-1, T_nat, [], ["%b"]) in + let nat_prim_c = Prim (-1, T_nat, [], ["%c"]) in + let nat_ty = Nat_t None in + let pair_prim l = Prim (-1, T_pair, l, []) in + let pair_ty ty1 ty2 = Pair_t ((ty1, None, None), (ty2, None, None), None) in + let pair_prim2 a b = pair_prim [a; b] in + let pair_nat_nat_prim = pair_prim2 nat_prim nat_prim in + let pair_nat_nat_ty = pair_ty nat_ty nat_ty in + test_context () + >>=? fun ctxt -> + (* pair nat nat *) + test_parse_ty ctxt pair_nat_nat_prim pair_nat_nat_ty + >>?= fun ctxt -> + (* pair (pair nat nat) nat *) + test_parse_ty + ctxt + (pair_prim2 pair_nat_nat_prim nat_prim) + (pair_ty pair_nat_nat_ty nat_ty) + >>?= fun ctxt -> + (* pair nat (pair nat nat) *) + test_parse_ty + ctxt + (pair_prim2 nat_prim pair_nat_nat_prim) + (pair_ty nat_ty pair_nat_nat_ty) + >>?= fun ctxt -> + (* pair nat nat nat *) + test_parse_ty + ctxt + (pair_prim [nat_prim; nat_prim; nat_prim]) + (pair_ty nat_ty pair_nat_nat_ty) + >>?= fun ctxt -> + (* pair (nat %a) nat *) + test_parse_ty + ctxt + (pair_prim2 nat_prim_a nat_prim) + (Pair_t ((nat_ty, Some (Field_annot "a"), None), (nat_ty, None, None), None)) + >>?= fun ctxt -> + (* pair nat (nat %b) *) + test_parse_ty + ctxt + (pair_prim2 nat_prim nat_prim_b) + (Pair_t ((nat_ty, None, None), (nat_ty, Some (Field_annot "b"), None), None)) + >>?= fun ctxt -> + (* pair (nat %a) (nat %b) *) + test_parse_ty + ctxt + (pair_prim2 nat_prim_a nat_prim_b) + (Pair_t + ( (nat_ty, Some (Field_annot "a"), None), + (nat_ty, Some (Field_annot "b"), None), + None )) + >>?= fun ctxt -> + (* pair (nat %a) (nat %b) (nat %c) *) + test_parse_ty + ctxt + (pair_prim [nat_prim_a; nat_prim_b; nat_prim_c]) + (Pair_t + ( (nat_ty, Some (Field_annot "a"), None), + ( Pair_t + ( (nat_ty, Some (Field_annot "b"), None), + (nat_ty, Some (Field_annot "c"), None), + None ), + None, + None ), + None )) + >>?= fun ctxt -> + (* pair (nat %a) (pair %b nat nat) *) + test_parse_ty + ctxt + (pair_prim2 nat_prim_a (Prim (-1, T_pair, [nat_prim; nat_prim], ["%b"]))) + (Pair_t + ( (nat_ty, Some (Field_annot "a"), None), + ( Pair_t ((nat_ty, None, None), (nat_ty, None, None), None), + Some (Field_annot "b"), + None ), + None )) + >>?= fun _ -> return_unit + +let test_unparse_ty loc ctxt expected ty = + Environment.wrap_tzresult + ( Script_ir_translator.unparse_ty ctxt ty + >>? fun (actual, ctxt) -> + if actual = expected then ok ctxt + else Alcotest.failf "Unexpected error: %s" loc ) + +let test_unparse_comb_type () = + let open Script in + let open Script_typed_ir in + let nat_prim = Prim (-1, T_nat, [], []) in + let nat_prim_a = Prim (-1, T_nat, [], ["%a"]) in + let nat_prim_b = Prim (-1, T_nat, [], ["%b"]) in + let nat_prim_c = Prim (-1, T_nat, [], ["%c"]) in + let nat_ty = Nat_t None in + let pair_prim l = Prim (-1, T_pair, l, []) in + let pair_ty ty1 ty2 = Pair_t ((ty1, None, None), (ty2, None, None), None) in + let pair_prim2 a b = pair_prim [a; b] in + let pair_nat_nat_prim = pair_prim2 nat_prim nat_prim in + let pair_nat_nat_ty = pair_ty nat_ty nat_ty in + test_context () + >>=? fun ctxt -> + (* pair nat nat *) + test_unparse_ty __LOC__ ctxt pair_nat_nat_prim pair_nat_nat_ty + >>?= fun ctxt -> + (* pair (pair nat nat) nat *) + test_unparse_ty + __LOC__ + ctxt + (pair_prim2 pair_nat_nat_prim nat_prim) + (pair_ty pair_nat_nat_ty nat_ty) + >>?= fun ctxt -> + (* pair nat nat nat *) + test_unparse_ty + __LOC__ + ctxt + (pair_prim [nat_prim; nat_prim; nat_prim]) + (pair_ty nat_ty pair_nat_nat_ty) + >>?= fun ctxt -> + (* pair (nat %a) nat *) + test_unparse_ty + __LOC__ + ctxt + (pair_prim2 nat_prim_a nat_prim) + (Pair_t ((nat_ty, Some (Field_annot "a"), None), (nat_ty, None, None), None)) + >>?= fun ctxt -> + (* pair nat (nat %b) *) + test_unparse_ty + __LOC__ + ctxt + (pair_prim2 nat_prim nat_prim_b) + (Pair_t ((nat_ty, None, None), (nat_ty, Some (Field_annot "b"), None), None)) + >>?= fun ctxt -> + (* pair (nat %a) (nat %b) *) + test_unparse_ty + __LOC__ + ctxt + (pair_prim2 nat_prim_a nat_prim_b) + (Pair_t + ( (nat_ty, Some (Field_annot "a"), None), + (nat_ty, Some (Field_annot "b"), None), + None )) + >>?= fun ctxt -> + (* pair (nat %a) (nat %b) (nat %c) *) + test_unparse_ty + __LOC__ + ctxt + (pair_prim [nat_prim_a; nat_prim_b; nat_prim_c]) + (Pair_t + ( (nat_ty, Some (Field_annot "a"), None), + ( Pair_t + ( (nat_ty, Some (Field_annot "b"), None), + (nat_ty, Some (Field_annot "c"), None), + None ), + None, + None ), + None )) + >>?= fun ctxt -> + (* pair (nat %a) (pair %b nat nat) *) + test_unparse_ty + __LOC__ + ctxt + (pair_prim2 nat_prim_a (Prim (-1, T_pair, [nat_prim; nat_prim], ["%b"]))) + (Pair_t + ( (nat_ty, Some (Field_annot "a"), None), + ( Pair_t ((nat_ty, None, None), (nat_ty, None, None), None), + Some (Field_annot "b"), + None ), + None )) + >>?= fun ctxt -> + (* pair nat (pair @b nat nat) *) + test_unparse_ty + __LOC__ + ctxt + (pair_prim2 nat_prim (Prim (-1, T_pair, [nat_prim; nat_prim], ["@b"]))) + (Pair_t + ( (nat_ty, None, None), + ( Pair_t ((nat_ty, None, None), (nat_ty, None, None), None), + None, + Some (Var_annot "b") ), + None )) + >>?= fun ctxt -> + (* pair nat (pair :b nat nat) *) + test_unparse_ty + __LOC__ + ctxt + (pair_prim2 nat_prim (Prim (-1, T_pair, [nat_prim; nat_prim], [":b"]))) + (Pair_t + ( (nat_ty, None, None), + ( Pair_t + ((nat_ty, None, None), (nat_ty, None, None), Some (Type_annot "b")), + None, + None ), + None )) + >>?= fun _ -> return_unit + +let test_unparse_comparable_ty loc ctxt expected ty = + (* unparse_comparable_ty is not exported, the simplest way to call it is to + call parse_ty on a set type *) + Environment.wrap_tzresult + ( Script_ir_translator.unparse_ty ctxt (Set_t (ty, None)) + >>? fun (actual, ctxt) -> + if actual = Prim (-1, T_set, [expected], []) then ok ctxt + else Alcotest.failf "Unexpected error: %s" loc ) + +let test_unparse_comb_comparable_type () = + let open Script in + let open Script_typed_ir in + let nat_prim = Prim (-1, T_nat, [], []) in + let nat_prim_a = Prim (-1, T_nat, [], ["%a"]) in + let nat_prim_b = Prim (-1, T_nat, [], ["%b"]) in + let nat_prim_c = Prim (-1, T_nat, [], ["%c"]) in + let nat_ty = Nat_key None in + let pair_prim l = Prim (-1, T_pair, l, []) in + let pair_ty ty1 ty2 = Pair_key ((ty1, None), (ty2, None), None) in + let pair_prim2 a b = pair_prim [a; b] in + let pair_nat_nat_prim = pair_prim2 nat_prim nat_prim in + let pair_nat_nat_ty = pair_ty nat_ty nat_ty in + test_context () + >>=? fun ctxt -> + (* pair nat nat *) + test_unparse_comparable_ty __LOC__ ctxt pair_nat_nat_prim pair_nat_nat_ty + >>?= fun ctxt -> + (* pair (pair nat nat) nat *) + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim2 pair_nat_nat_prim nat_prim) + (pair_ty pair_nat_nat_ty nat_ty) + >>?= fun ctxt -> + (* pair nat nat nat *) + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim [nat_prim; nat_prim; nat_prim]) + (pair_ty nat_ty pair_nat_nat_ty) + >>?= fun ctxt -> + (* pair (nat %a) nat *) + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim2 nat_prim_a nat_prim) + (Pair_key ((nat_ty, Some (Field_annot "a")), (nat_ty, None), None)) + >>?= fun ctxt -> + (* pair nat (nat %b) *) + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim2 nat_prim nat_prim_b) + (Pair_key ((nat_ty, None), (nat_ty, Some (Field_annot "b")), None)) + >>?= fun ctxt -> + (* pair (nat %a) (nat %b) *) + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim2 nat_prim_a nat_prim_b) + (Pair_key + ( (nat_ty, Some (Field_annot "a")), + (nat_ty, Some (Field_annot "b")), + None )) + >>?= fun ctxt -> + (* pair (nat %a) (nat %b) (nat %c) *) + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim [nat_prim_a; nat_prim_b; nat_prim_c]) + (Pair_key + ( (nat_ty, Some (Field_annot "a")), + ( Pair_key + ( (nat_ty, Some (Field_annot "b")), + (nat_ty, Some (Field_annot "c")), + None ), + None ), + None )) + >>?= fun ctxt -> + (* pair (nat %a) (pair %b nat nat) *) + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim2 nat_prim_a (Prim (-1, T_pair, [nat_prim; nat_prim], ["%b"]))) + (Pair_key + ( (nat_ty, Some (Field_annot "a")), + ( Pair_key ((nat_ty, None), (nat_ty, None), None), + Some (Field_annot "b") ), + None )) + >>?= fun ctxt -> + (* pair nat (pair :b nat nat) *) + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim2 nat_prim (Prim (-1, T_pair, [nat_prim; nat_prim], [":b"]))) + (Pair_key + ( (nat_ty, None), + ( Pair_key ((nat_ty, None), (nat_ty, None), Some (Type_annot "b")), + None ), + None )) + >>?= fun _ -> return_unit + +let test_parse_data ?(equal = Stdlib.( = )) loc ctxt ty node expected = + let legacy = false in + let allow_forged = true in + wrap_error_lwt + ( Script_ir_translator.parse_data ctxt ~legacy ~allow_forged ty node + >>=? fun (actual, ctxt) -> + if equal actual expected then return ctxt + else Alcotest.failf "Unexpected error: %s" loc ) + +let test_parse_data_fails loc ctxt ty node = + let legacy = false in + let allow_forged = false in + wrap_error_lwt + ( Script_ir_translator.parse_data ctxt ~legacy ~allow_forged ty node + >>= function + | Ok _ -> + Alcotest.failf "Unexpected typechecking success: %s" loc + | Error trace -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + let expect_id = "michelson_v1.invalid_constant" in + let expect_descrfiption = + "A data expression was invalid for its expected type." + in + if + Astring.String.is_infix ~affix:expect_id trace_string + && Astring.String.is_infix ~affix:expect_descrfiption trace_string + then return_unit + else + Alcotest.failf + "Unexpected error (%s) at %s" + trace_string + __LOC__ + return_unit ) + +let test_parse_comb_data () = + let open Script in + let open Script_typed_ir in + let z = Script_int.zero_n in + let z_prim = Micheline.Int (-1, Z.zero) in + let nat_ty = Nat_t None in + let pair_prim l = Prim (-1, D_Pair, l, []) in + let pair_ty ty1 ty2 = Pair_t ((ty1, None, None), (ty2, None, None), None) in + let pair_nat_nat_ty = pair_ty nat_ty nat_ty in + let pair_prim2 a b = pair_prim [a; b] in + let pair_z_z_prim = pair_prim2 z_prim z_prim in + let list_nat_ty = List_t (nat_ty, None) in + let big_map_nat_nat_ty = Big_map_t (Nat_key None, nat_ty, None) in + test_context_with_nat_nat_big_map () + >>=? fun (ctxt, big_map_id) -> + (* Pair 0 0 *) + test_parse_data __LOC__ ctxt (pair_ty nat_ty nat_ty) pair_z_z_prim (z, z) + >>=? fun ctxt -> + (* {0; 0} *) + test_parse_data + __LOC__ + ctxt + (pair_ty nat_ty nat_ty) + (Micheline.Seq (-1, [z_prim; z_prim])) + (z, z) + >>=? fun ctxt -> + (* Pair (Pair 0 0) 0 *) + test_parse_data + __LOC__ + ctxt + (pair_ty pair_nat_nat_ty nat_ty) + (pair_prim2 pair_z_z_prim z_prim) + ((z, z), z) + >>=? fun ctxt -> + (* Pair 0 (Pair 0 0) *) + test_parse_data + __LOC__ + ctxt + (pair_ty nat_ty pair_nat_nat_ty) + (pair_prim2 z_prim pair_z_z_prim) + (z, (z, z)) + >>=? fun ctxt -> + (* Pair 0 0 0 *) + test_parse_data + __LOC__ + ctxt + (pair_ty nat_ty pair_nat_nat_ty) + (pair_prim [z_prim; z_prim; z_prim]) + (z, (z, z)) + >>=? fun ctxt -> + (* {0; 0; 0} *) + test_parse_data + __LOC__ + ctxt + (pair_ty nat_ty pair_nat_nat_ty) + (Micheline.Seq (-1, [z_prim; z_prim; z_prim])) + (z, (z, z)) + >>=? fun ctxt -> + (* Should fail: {0} against pair nat (list nat) *) + test_parse_data_fails + __LOC__ + ctxt + (pair_ty nat_ty list_nat_ty) + (Micheline.Seq (-1, [z_prim])) + >>=? fun () -> + (* Should fail: {0; 0; 0} against pair nat (list nat) *) + test_parse_data_fails + __LOC__ + ctxt + (pair_ty nat_ty list_nat_ty) + (Micheline.Seq (-1, [z_prim; z_prim; z_prim])) + >>=? fun () -> + (* check Pair 0 (Pair 0 {}) against pair nat (big_map nat nat) + so that the following test fails for the good reason and not because + the big map doesn't exist + *) + let id_z = Big_map.Id.unparse_to_z big_map_id in + let id_prim = Int (-1, id_z) in + let expected_big_map = + let open Script_typed_ir in + let diff = {map = Big_map_overlay.empty; size = 0} in + let nat_key_ty = Nat_key None in + {id = Some big_map_id; diff; key_type = nat_key_ty; value_type = nat_ty} + in + let equal (nat1, big_map1) (nat2, big_map2) = + (* Custom equal needed because big maps contain boxed maps containing functional values *) + nat1 = nat2 && big_map1.id = big_map2.id + && big_map1.key_type = big_map2.key_type + && big_map1.value_type = big_map2.value_type + && big_map1.diff.size = big_map2.diff.size + && Big_map_overlay.bindings big_map1.diff.map + = Big_map_overlay.bindings big_map2.diff.map + in + test_parse_data + ~equal + __LOC__ + ctxt + (pair_ty nat_ty big_map_nat_nat_ty) + (pair_prim2 z_prim (pair_prim2 id_prim (Seq (-1, [])))) + (Script_int.zero_n, expected_big_map) + >>=? fun ctxt -> + (* Should fail: Pair 0 0 {} against pair nat (big_map nat nat) *) + test_parse_data_fails + __LOC__ + ctxt + (pair_ty nat_ty big_map_nat_nat_ty) + (pair_prim [z_prim; id_prim; Seq (-1, [])]) + +let test_parse_address () = + test_context_with_nat_nat_big_map () + >>=? fun (ctxt, _big_map_id) -> + (* KT1% (empty entrypoint) *) + wrap_error_lwt + (Lwt.return (Contract.of_b58check "KT1FAKEFAKEFAKEFAKEFAKEFAKEFAKGGSE2x")) + >>=? fun kt1fake -> + test_parse_data + __LOC__ + ctxt + (Address_t None) + (String (-1, "KT1FAKEFAKEFAKEFAKEFAKEFAKEFAKGGSE2x%")) + (kt1fake, "default") + >>=? fun ctxt -> + (* tz1% (empty entrypoint) *) + wrap_error_lwt + (Lwt.return (Contract.of_b58check "tz1fakefakefakefakefakefakefakcphLA5")) + >>=? fun tz1fake -> + test_parse_data + __LOC__ + ctxt + (Address_t None) + (String (-1, "tz1fakefakefakefakefakefakefakcphLA5%")) + (tz1fake, "default") + >|=? fun _ctxt -> () + +let test_unparse_data loc ctxt ty x ~expected_readable ~expected_optimized = + wrap_error_lwt + ( Script_ir_translator.unparse_data ctxt Script_ir_translator.Readable ty x + >>=? fun (actual_readable, ctxt) -> + ( if actual_readable = expected_readable then return ctxt + else Alcotest.failf "Error in readable unparsing: %s" loc ) + >>=? fun ctxt -> + Script_ir_translator.unparse_data ctxt Script_ir_translator.Optimized ty x + >>=? fun (actual_optimized, ctxt) -> + if actual_optimized = expected_optimized then return ctxt + else Alcotest.failf "Error in optimized unparsing: %s" loc ) + +let test_unparse_comb_data () = + let open Script in + let open Script_typed_ir in + let z = Script_int.zero_n in + let z_prim = Micheline.Int (-1, Z.zero) in + let nat_ty = Nat_t None in + let pair_prim l = Prim (-1, D_Pair, l, []) in + let pair_ty ty1 ty2 = Pair_t ((ty1, None, None), (ty2, None, None), None) in + let pair_nat_nat_ty = pair_ty nat_ty nat_ty in + let pair_prim2 a b = pair_prim [a; b] in + let pair_z_z_prim = pair_prim2 z_prim z_prim in + test_context () + >>=? fun ctxt -> + (* Pair 0 0 *) + test_unparse_data + __LOC__ + ctxt + (pair_ty nat_ty nat_ty) + (z, z) + ~expected_readable:pair_z_z_prim + ~expected_optimized:pair_z_z_prim + >>=? fun ctxt -> + (* Pair (Pair 0 0) 0 *) + test_unparse_data + __LOC__ + ctxt + (pair_ty pair_nat_nat_ty nat_ty) + ((z, z), z) + ~expected_readable:(pair_prim2 pair_z_z_prim z_prim) + ~expected_optimized:(pair_prim2 pair_z_z_prim z_prim) + >>=? fun ctxt -> + (* Readable: Pair 0 0 0; Optimized: Pair 0 (Pair 0 0) *) + test_unparse_data + __LOC__ + ctxt + (pair_ty nat_ty pair_nat_nat_ty) + (z, (z, z)) + ~expected_readable:(pair_prim [z_prim; z_prim; z_prim]) + ~expected_optimized:(pair_prim2 z_prim pair_z_z_prim) + >>=? fun ctxt -> + (* Readable: Pair 0 0 0 0; Optimized: {0; 0; 0; 0} *) + test_unparse_data + __LOC__ + ctxt + (pair_ty nat_ty (pair_ty nat_ty pair_nat_nat_ty)) + (z, (z, (z, z))) + ~expected_readable:(pair_prim [z_prim; z_prim; z_prim; z_prim]) + ~expected_optimized:(Micheline.Seq (-1, [z_prim; z_prim; z_prim; z_prim])) + >>=? fun _ -> return_unit + +(* Generate all the possible syntaxes for pairs *) +let gen_pairs left right = + [Prim (-1, Script.D_Pair, [left; right], []); Seq (-1, [left; right])] + +(* Generate all the possible syntaxes for combs *) +let rec gen_combs leaf arity = + assert (arity >= 2) ; + if arity = 2 then gen_pairs leaf leaf + else + gen_combs leaf (arity - 1) + |> List.map (fun smaller -> + ( match smaller with + | Prim (loc, Script.D_Pair, vs, []) -> + Prim (loc, Script.D_Pair, leaf :: vs, []) + | Seq (loc, vs) -> + Seq (loc, leaf :: vs) + | _ -> + assert false ) + :: gen_pairs leaf smaller) + |> List.flatten + +(* Checks the optimality of the Optimized Micheline representation for combs *) +let test_optimal_comb () = + let open Script_typed_ir in + let leaf_ty = Nat_t None in + let leaf_mich = Int (-1, Z.zero) in + let leaf_v = Script_int.zero_n in + let size_of_micheline mich = + let canonical = Micheline.strip_locations mich in + ( canonical, + Bytes.length + @@ Data_encoding.Binary.to_bytes_exn Script.expr_encoding canonical ) + in + let check_optimal_comb loc ctxt ty v arity = + wrap_error_lwt + ( Script_ir_translator.unparse_data + ctxt + Script_ir_translator.Optimized + ty + v + >>=? fun (unparsed, ctxt) -> + let (unparsed_canonical, unparsed_size) = size_of_micheline unparsed in + List.iter_es (fun other_repr -> + let (other_repr_canonical, other_repr_size) = + size_of_micheline other_repr + in + if other_repr_size < unparsed_size then + Alcotest.failf + "At %s, for comb of arity %d, representation %a (size %d bytes) \ + is shorter than representation %a (size %d bytes) returned by \ + unparse_data in Optimized mode" + loc + arity + Michelson_v1_printer.print_expr + other_repr_canonical + other_repr_size + Michelson_v1_printer.print_expr + unparsed_canonical + unparsed_size + else return_unit) + @@ gen_combs leaf_mich arity + >>=? fun () -> return ctxt ) + in + let pair_ty ty1 ty2 = Pair_t ((ty1, None, None), (ty2, None, None), None) in + test_context () + >>=? fun ctxt -> + let comb2_ty = pair_ty leaf_ty leaf_ty in + let comb2_v = (leaf_v, leaf_v) in + check_optimal_comb __LOC__ ctxt comb2_ty comb2_v 2 + >>=? fun ctxt -> + let comb3_ty = pair_ty leaf_ty comb2_ty in + let comb3_v = (leaf_v, comb2_v) in + check_optimal_comb __LOC__ ctxt comb3_ty comb3_v 3 + >>=? fun ctxt -> + let comb4_ty = pair_ty leaf_ty comb3_ty in + let comb4_v = (leaf_v, comb3_v) in + check_optimal_comb __LOC__ ctxt comb4_ty comb4_v 4 + >>=? fun ctxt -> + let comb5_ty = pair_ty leaf_ty comb4_ty in + let comb5_v = (leaf_v, comb4_v) in + check_optimal_comb __LOC__ ctxt comb5_ty comb5_v 5 + >>=? fun _ctxt -> return_unit + +let tests = + [ Test_services.tztest + "test typecheck stack overflow error" + `Quick + test_typecheck_stack_overflow; + Test_services.tztest "test comb type parsing" `Quick test_parse_comb_type; + Test_services.tztest + "test comb type unparsing" + `Quick + test_unparse_comb_type; + Test_services.tztest + "test comb comparable type unparsing" + `Quick + test_unparse_comb_comparable_type; + Test_services.tztest "test comb data parsing" `Quick test_parse_comb_data; + Test_services.tztest + "test comb data unparsing" + `Quick + test_unparse_comb_data; + Test_services.tztest + "test optimal comb data unparsing" + `Quick + test_optimal_comb; + Test_services.tztest "test parse address" `Quick test_parse_address ] diff --git a/src/proto_009_PsFLoren/lib_protocol/test/test_voting.ml b/src/proto_009_PsFLoren/lib_protocol/test/test_voting.ml new file mode 100644 index 0000000000000000000000000000000000000000..4858c860468bdb7ba087d154ce1dfcdc0b56e78d --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/test/test_voting.ml @@ -0,0 +1,1285 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (voting) + Invocation: dune exec src/proto_alpha/lib_protocol/test/main.exe -- test "^voting$" + Subject: On the voting process. +*) + +open Protocol + +(* missing stuff in Alpha_context.Vote *) +let ballots_zero = Alpha_context.Vote.{yay = 0l; nay = 0l; pass = 0l} + +let ballots_equal b1 b2 = + Alpha_context.Vote.(b1.yay = b2.yay && b1.nay = b2.nay && b1.pass = b2.pass) + +let ballots_pp ppf v = + Alpha_context.Vote.( + Format.fprintf + ppf + "{ yay = %ld ; nay = %ld ; pass = %ld" + v.yay + v.nay + v.pass) + +(* constants and ratios used in voting: + percent_mul denotes the percent multiplier + initial_participation is 7000 that is, 7/10 * percent_mul + the participation EMA ratio pr_ema_weight / den = 7 / 10 + the participation ratio pr_num / den = 2 / 10 + note: we use the same denominator for both participation EMA and participation rate. + supermajority rate is s_num / s_den = 8 / 10 *) +let percent_mul = 100_00 + +let den = 10 + +let initial_participation_num = 7 + +let initial_participation = initial_participation_num * percent_mul / den + +let pr_ema_weight = 8 + +let pr_num = den - pr_ema_weight + +let s_num = 8 + +let s_den = 10 + +let qr_min_num = 2 + +let qr_max_num = 7 + +let expected_qr_num participation_ema = + let participation_ema = Int32.to_int participation_ema in + let participation_ema = participation_ema * den / percent_mul in + Float.( + of_int qr_min_num + +. of_int participation_ema + *. (of_int qr_max_num -. of_int qr_min_num) + /. of_int den) + +(* Protocol_hash.zero is "PrihK96nBAFSxVL1GLJTVhu9YnzkMFiBeuJRPA8NwuZVZCE1L6i" *) +let protos = + Array.map + (fun s -> Protocol_hash.of_b58check_exn s) + [| "ProtoALphaALphaALphaALphaALphaALphaALpha61322gcLUGH"; + "ProtoALphaALphaALphaALphaALphaALphaALphabc2a7ebx6WB"; + "ProtoALphaALphaALphaALphaALphaALphaALpha84efbeiF6cm"; + "ProtoALphaALphaALphaALphaALphaALphaALpha91249Z65tWS"; + "ProtoALphaALphaALphaALphaALphaALphaALpha537f5h25LnN"; + "ProtoALphaALphaALphaALphaALphaALphaALpha5c8fefgDYkr"; + "ProtoALphaALphaALphaALphaALphaALphaALpha3f31feSSarC"; + "ProtoALphaALphaALphaALphaALphaALphaALphabe31ahnkxSC"; + "ProtoALphaALphaALphaALphaALphaALphaALphabab3bgRb7zQ"; + "ProtoALphaALphaALphaALphaALphaALphaALphaf8d39cctbpk"; + "ProtoALphaALphaALphaALphaALphaALphaALpha3b981byuYxD"; + "ProtoALphaALphaALphaALphaALphaALphaALphaa116bccYowi"; + "ProtoALphaALphaALphaALphaALphaALphaALphacce68eHqboj"; + "ProtoALphaALphaALphaALphaALphaALphaALpha225c7YrWwR7"; + "ProtoALphaALphaALphaALphaALphaALphaALpha58743cJL6FG"; + "ProtoALphaALphaALphaALphaALphaALphaALphac91bcdvmJFR"; + "ProtoALphaALphaALphaALphaALphaALphaALpha1faaadhV7oW"; + "ProtoALphaALphaALphaALphaALphaALphaALpha98232gD94QJ"; + "ProtoALphaALphaALphaALphaALphaALphaALpha9d1d8cijvAh"; + "ProtoALphaALphaALphaALphaALphaALphaALphaeec52dKF6Gx"; + "ProtoALphaALphaALphaALphaALphaALphaALpha841f2cQqajX" |] + +(** helper functions *) + +let assert_period_kind expected_kind kind loc = + if Stdlib.(expected_kind = kind) then return_unit + else + Alcotest.failf + "%s - Unexpected voting period kind - expected %a, got %a" + loc + Alpha_context.Voting_period.pp_kind + expected_kind + Alpha_context.Voting_period.pp_kind + kind + +let assert_period_index expected_index index loc = + if expected_index = index then return_unit + else + Alcotest.failf + "%s - Unexpected voting period index - expected %ld, got %ld" + loc + expected_index + index + +let assert_period_position expected_position position loc = + if position = expected_position then return_unit + else + Alcotest.failf + "%s - Unexpected voting period position blocks - expected %ld, got %ld" + loc + expected_position + position + +let assert_period_remaining expected_remaining remaining loc = + if remaining = expected_remaining then return_unit + else + Alcotest.failf + "%s - Unexpected voting period remaining blocks - expected %ld, got %ld" + loc + expected_remaining + remaining + +let assert_period ?expected_kind ?expected_index ?expected_position + ?expected_remaining b loc = + Context.Vote.get_current_period (B b) + >>=? fun {voting_period; position; remaining} -> + ( if Option.is_some expected_kind then + assert_period_kind + (WithExceptions.Option.get ~loc:__LOC__ expected_kind) + voting_period.kind + loc + else return_unit ) + >>=? fun () -> + ( if Option.is_some expected_index then + assert_period_index + (WithExceptions.Option.get ~loc:__LOC__ expected_index) + voting_period.index + loc + else return_unit ) + >>=? fun () -> + ( if Option.is_some expected_position then + assert_period_position + (WithExceptions.Option.get ~loc:__LOC__ expected_position) + position + loc + else return_unit ) + >>=? fun () -> + if Option.is_some expected_remaining then + assert_period_remaining + (WithExceptions.Option.get ~loc:__LOC__ expected_remaining) + remaining + loc + else return_unit + +let mk_contracts_from_pkh pkh_list = + List.map Alpha_context.Contract.implicit_contract pkh_list + +(* get the list of delegates and the list of their rolls from listings *) +let get_delegates_and_rolls_from_listings b = + Context.Vote.get_listings (B b) + >|=? fun l -> (mk_contracts_from_pkh (List.map fst l), List.map snd l) + +(* compute the rolls of each delegate *) +let get_rolls b delegates loc = + Context.Vote.get_listings (B b) + >>=? fun l -> + List.map_es + (fun delegate -> + Context.Contract.pkh delegate + >>=? fun pkh -> + match List.find_opt (fun (del, _) -> del = pkh) l with + | None -> + failwith "%s - Missing delegate" loc + | Some (_, rolls) -> + return rolls) + delegates + +(* Checks that the listings are populated *) +let assert_listings_not_empty b ~loc = + Context.Vote.get_listings (B b) + >>=? function + | [] -> failwith "Unexpected empty listings (%s)" loc | _ -> return_unit + +let bake_until_first_block_of_next_period b = + Context.Vote.get_current_period (B b) + >>=? fun {remaining; _} -> Block.bake_n Int32.(add remaining one |> to_int) b + +(** A normal and successful vote sequence. *) +let test_successful_vote num_delegates () = + let open Alpha_context in + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + Context.init ~min_proposal_quorum num_delegates + >>=? fun (b, _) -> + (* no ballots in proposal period *) + Context.Vote.get_ballots (B b) + >>=? fun v -> + Assert.equal + ~loc:__LOC__ + ballots_equal + "Unexpected ballots" + ballots_pp + v + ballots_zero + >>=? fun () -> + (* no ballots in proposal period *) + Context.Vote.get_ballot_list (B b) + >>=? (function + | [] -> + return_unit + | _ -> + failwith "%s - Unexpected ballot list" __LOC__) + >>=? fun () -> + (* Last baked block is first block of period Proposal *) + assert_period + ~expected_kind:Proposal + ~expected_index:0l + ~expected_position:0l + b + __LOC__ + >>=? fun () -> + assert_listings_not_empty b ~loc:__LOC__ + >>=? fun () -> + (* participation EMA starts at initial_participation *) + Context.Vote.get_participation_ema b + >>=? fun v -> + Assert.equal_int ~loc:__LOC__ initial_participation (Int32.to_int v) + >>=? fun () -> + (* listings must be populated in proposal period *) + assert_listings_not_empty b ~loc:__LOC__ + >>=? fun () -> + (* beginning of proposal, denoted by _p1; + take a snapshot of the active delegates and their rolls from listings *) + get_delegates_and_rolls_from_listings b + >>=? fun (delegates_p1, rolls_p1) -> + (* no proposals at the beginning of proposal period *) + Context.Vote.get_proposals (B b) + >>=? fun ps -> + ( if Environment.Protocol_hash.Map.is_empty ps then return_unit + else failwith "%s - Unexpected proposals" __LOC__ ) + >>=? fun () -> + (* no current proposal during proposal period *) + Context.Vote.get_current_proposal (B b) + >>=? (function + | None -> + return_unit + | Some _ -> + failwith "%s - Unexpected proposal" __LOC__) + >>=? fun () -> + let del1 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates_p1 0 + in + let del2 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates_p1 1 + in + let props = + List.map (fun i -> protos.(i)) (2 -- Constants.max_proposals_per_delegate) + in + Op.proposals (B b) del1 (Protocol_hash.zero :: props) + >>=? fun ops1 -> + Op.proposals (B b) del2 [Protocol_hash.zero] + >>=? fun ops2 -> + Block.bake ~operations:[ops1; ops2] b + >>=? fun b -> + (* proposals are now populated *) + Context.Vote.get_proposals (B b) + >>=? fun ps -> + (* correctly count the double proposal for zero *) + (let weight = + Int32.add + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth rolls_p1 0) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth rolls_p1 1) + in + match Environment.Protocol_hash.(Map.find_opt zero ps) with + | Some v -> + if v = weight then return_unit + else failwith "%s - Wrong count %ld is not %ld" __LOC__ v weight + | None -> + failwith "%s - Missing proposal" __LOC__) + >>=? fun () -> + (* proposing more than maximum_proposals fails *) + Op.proposals (B b) del1 (Protocol_hash.zero :: props) + >>=? fun ops -> + Block.bake ~operations:[ops] b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Amendment.Too_many_proposals -> + true + | _ -> + false) + >>=? fun () -> + (* proposing less than one proposal fails *) + Op.proposals (B b) del1 [] + >>=? fun ops -> + Block.bake ~operations:[ops] b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Amendment.Empty_proposal -> + true + | _ -> + false) + >>=? fun () -> + (* first block of exploration period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* next block is first block of exploration *) + assert_period ~expected_kind:Exploration ~expected_index:1l b __LOC__ + >>=? fun () -> + assert_listings_not_empty b ~loc:__LOC__ + >>=? fun () -> + (* listings must be populated in proposal period before moving to exploration period *) + assert_listings_not_empty b ~loc:__LOC__ + >>=? fun () -> + (* beginning of exploration period, denoted by _p2; + take a snapshot of the active delegates and their rolls from listings *) + get_delegates_and_rolls_from_listings b + >>=? fun (delegates_p2, rolls_p2) -> + (* no proposals during exploration period *) + Context.Vote.get_proposals (B b) + >>=? fun ps -> + ( if Environment.Protocol_hash.Map.is_empty ps then return_unit + else failwith "%s - Unexpected proposals" __LOC__ ) + >>=? fun () -> + (* current proposal must be set during exploration period *) + Context.Vote.get_current_proposal (B b) + >>=? (function + | Some v -> + if Protocol_hash.(equal zero v) then return_unit + else failwith "%s - Wrong proposal" __LOC__ + | None -> + failwith "%s - Missing proposal" __LOC__) + >>=? fun () -> + (* unanimous vote: all delegates --active when p2 started-- vote *) + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + delegates_p2 + >>=? fun operations -> + Block.bake ~operations b + >>=? fun b -> + Op.ballot (B b) del1 Protocol_hash.zero Vote.Nay + >>=? fun op -> + Block.bake ~operations:[op] b + >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Amendment.Unauthorized_ballot -> + true + | _ -> + false) + >>=? fun () -> + (* Allocate votes from weight (rolls) of active delegates *) + List.fold_left (fun acc v -> Int32.(add v acc)) 0l rolls_p2 + |> fun rolls_sum -> + (* # of Yay rolls in ballots matches votes of the delegates *) + Context.Vote.get_ballots (B b) + >>=? fun v -> + Assert.equal + ~loc:__LOC__ + ballots_equal + "Unexpected ballots" + ballots_pp + v + Vote.{yay = rolls_sum; nay = 0l; pass = 0l} + >>=? fun () -> + (* One Yay ballot per delegate *) + Context.Vote.get_ballot_list (B b) + >>=? (function + | [] -> + failwith "%s - Unexpected empty ballot list" __LOC__ + | l -> + List.iter_es + (fun delegate -> + Context.Contract.pkh delegate + >>=? fun pkh -> + match List.find_opt (fun (del, _) -> del = pkh) l with + | None -> + failwith "%s - Missing delegate" __LOC__ + | Some (_, Vote.Yay) -> + return_unit + | Some _ -> + failwith "%s - Wrong ballot" __LOC__) + delegates_p2) + >>=? fun () -> + (* skip to cooldown period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + assert_period ~expected_index:2l ~expected_kind:Cooldown b __LOC__ + >>=? fun () -> + (* no ballots in cooldown period *) + Context.Vote.get_ballots (B b) + >>=? fun v -> + Assert.equal + ~loc:__LOC__ + ballots_equal + "Unexpected ballots" + ballots_pp + v + ballots_zero + >>=? fun () -> + (* listings must be populated in cooldown period before moving to promotion_vote period *) + assert_listings_not_empty b ~loc:__LOC__ + >>=? fun () -> + (* skip to promotion period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + assert_period ~expected_kind:Promotion ~expected_index:3l b __LOC__ + >>=? fun () -> + assert_listings_not_empty b ~loc:__LOC__ + >>=? fun () -> + (* period 3 *) + (* listings must be populated in promotion period *) + assert_listings_not_empty b ~loc:__LOC__ + >>=? fun () -> + (* beginning of promotion period, denoted by _p4; + take a snapshot of the active delegates and their rolls from listings *) + get_delegates_and_rolls_from_listings b + >>=? fun (delegates_p4, rolls_p4) -> + (* no proposals during promotion period *) + Context.Vote.get_proposals (B b) + >>=? fun ps -> + ( if Environment.Protocol_hash.Map.is_empty ps then return_unit + else failwith "%s - Unexpected proposals" __LOC__ ) + >>=? fun () -> + (* current proposal must be set during promotion period *) + Context.Vote.get_current_proposal (B b) + >>=? (function + | Some v -> + if Protocol_hash.(equal zero v) then return_unit + else failwith "%s - Wrong proposal" __LOC__ + | None -> + failwith "%s - Missing proposal" __LOC__) + >>=? fun () -> + (* unanimous vote: all delegates --active when p4 started-- vote *) + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + delegates_p4 + >>=? fun operations -> + Block.bake ~operations b + >>=? fun b -> + List.fold_left (fun acc v -> Int32.(add v acc)) 0l rolls_p4 + |> fun rolls_sum -> + (* # of Yays in ballots matches rolls of the delegate *) + Context.Vote.get_ballots (B b) + >>=? fun v -> + Assert.equal + ~loc:__LOC__ + ballots_equal + "Unexpected ballots" + ballots_pp + v + Vote.{yay = rolls_sum; nay = 0l; pass = 0l} + >>=? fun () -> + (* One Yay ballot per delegate *) + Context.Vote.get_ballot_list (B b) + >>=? (function + | [] -> + failwith "%s - Unexpected empty ballot list" __LOC__ + | l -> + List.iter_es + (fun delegate -> + Context.Contract.pkh delegate + >>=? fun pkh -> + match List.find_opt (fun (del, _) -> del = pkh) l with + | None -> + failwith "%s - Missing delegate" __LOC__ + | Some (_, Vote.Yay) -> + return_unit + | Some _ -> + failwith "%s - Wrong ballot" __LOC__) + delegates_p4) + >>=? fun () -> + (* skip to end of promotion period and activation*) + bake_until_first_block_of_next_period b + >>=? fun b -> + assert_period ~expected_kind:Adoption ~expected_index:4l b __LOC__ + >>=? fun () -> + (* skip to end of Adoption period and bake 1 more to activate *) + bake_until_first_block_of_next_period b + >>=? fun b -> + assert_period ~expected_kind:Proposal ~expected_index:5l b __LOC__ + >>=? fun () -> + assert_listings_not_empty b ~loc:__LOC__ + >>=? fun () -> + (* zero is the new protocol (before the vote this value is unset) *) + Context.Vote.get_protocol b + >>= fun p -> + Assert.equal + ~loc:__LOC__ + Protocol_hash.equal + "Unexpected proposal" + Protocol_hash.pp + p + Protocol_hash.zero + >>=? fun () -> return_unit + +(* given a list of active delegates, + return the first k active delegates with which one can have quorum, that is: + their roll sum divided by the total roll sum is bigger than pr_ema_weight/den *) +let get_smallest_prefix_voters_for_quorum active_delegates active_rolls + participation_ema = + let expected_quorum = expected_qr_num participation_ema in + List.fold_left (fun acc v -> Int32.(add v acc)) 0l active_rolls + |> fun active_rolls_sum -> + let rec loop delegates rolls sum selected = + match (delegates, rolls) with + | ([], []) -> + selected + | (del :: delegates, del_rolls :: rolls) -> + if + den * sum + < Float.to_int (expected_quorum *. Int32.to_float active_rolls_sum) + then + loop delegates rolls (sum + Int32.to_int del_rolls) (del :: selected) + else selected + | (_, _) -> + [] + in + loop active_delegates active_rolls 0 [] + +let get_expected_participation_ema rolls voter_rolls old_participation_ema = + (* formula to compute the updated participation_ema *) + let get_updated_participation_ema old_participation_ema participation = + ( (pr_ema_weight * Int32.to_int old_participation_ema) + + (pr_num * participation) ) + / den + in + List.fold_left (fun acc v -> Int32.(add v acc)) 0l rolls + |> fun rolls_sum -> + List.fold_left (fun acc v -> Int32.(add v acc)) 0l voter_rolls + |> fun voter_rolls_sum -> + let participation = + Int32.to_int voter_rolls_sum * percent_mul / Int32.to_int rolls_sum + in + get_updated_participation_ema old_participation_ema participation + +(** If not enough quorum + -- get_updated_participation_ema < pr_ema_weight/den -- + in exploration, go back to proposal period. *) +let test_not_enough_quorum_in_exploration num_delegates () = + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + Context.init ~min_proposal_quorum num_delegates + >>=? fun (b, delegates) -> + (* proposal period *) + let open Alpha_context in + assert_period ~expected_kind:Proposal b __LOC__ + >>=? fun () -> + let proposer = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 + in + Op.proposals (B b) proposer [Protocol_hash.zero] + >>=? fun ops -> + Block.bake ~operations:[ops] b + >>=? fun b -> + (* skip to exploration period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* we moved to an exploration period with one proposal *) + assert_period ~expected_kind:Exploration b __LOC__ + >>=? fun () -> + Context.Vote.get_participation_ema b + >>=? fun initial_participation_ema -> + (* beginning of exploration period, denoted by _p2; + take a snapshot of the active delegates and their rolls from listings *) + get_delegates_and_rolls_from_listings b + >>=? fun (delegates_p2, rolls_p2) -> + Context.Vote.get_participation_ema b + >>=? fun participation_ema -> + get_smallest_prefix_voters_for_quorum delegates_p2 rolls_p2 participation_ema + |> fun voters -> + (* take the first two voters out so there cannot be quorum *) + let voters_without_quorum = + WithExceptions.Option.get ~loc:__LOC__ @@ List.tl voters + in + get_rolls b voters_without_quorum __LOC__ + >>=? fun voters_rolls_in_exploration -> + (* all voters_without_quorum vote, for yays; + no nays, so supermajority is satisfied *) + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + voters_without_quorum + >>=? fun operations -> + Block.bake ~operations b + >>=? fun b -> + (* bake to next period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* we move back to the proposal period because not enough quorum *) + assert_period ~expected_kind:Proposal b __LOC__ + >>=? fun () -> + (* check participation_ema update *) + get_expected_participation_ema + rolls_p2 + voters_rolls_in_exploration + initial_participation_ema + |> fun expected_participation_ema -> + Context.Vote.get_participation_ema b + >>=? fun new_participation_ema -> + (* assert the formula to calculate participation_ema is correct *) + Assert.equal_int + ~loc:__LOC__ + expected_participation_ema + (Int32.to_int new_participation_ema) + >>=? fun () -> return_unit + +(** If not enough quorum + -- get_updated_participation_ema < pr_ema_weight/den -- + In promotion period, go back to proposal period. *) +let test_not_enough_quorum_in_promotion num_delegates () = + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + Context.init ~min_proposal_quorum num_delegates + >>=? fun (b, delegates) -> + assert_period ~expected_kind:Proposal b __LOC__ + >>=? fun () -> + let proposer = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 + in + Op.proposals (B b) proposer [Protocol_hash.zero] + >>=? fun ops -> + Block.bake ~operations:[ops] b + >>=? fun b -> + (* skip to exploration period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* we moved to an exploration period with one proposal *) + assert_period ~expected_kind:Exploration b __LOC__ + >>=? fun () -> + (* beginning of exploration period, denoted by _p2; + take a snapshot of the active delegates and their rolls from listings *) + get_delegates_and_rolls_from_listings b + >>=? fun (delegates_p2, rolls_p2) -> + Context.Vote.get_participation_ema b + >>=? fun participation_ema -> + get_smallest_prefix_voters_for_quorum delegates_p2 rolls_p2 participation_ema + |> fun voters -> + let open Alpha_context in + (* all voters vote, for yays; + no nays, so supermajority is satisfied *) + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + voters + >>=? fun operations -> + Block.bake ~operations b + >>=? fun b -> + (* skip to first block cooldown period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* we move to cooldown because we have supermajority and enough quorum *) + assert_period ~expected_kind:Cooldown b __LOC__ + >>=? fun () -> + (* skip to first block of promotion period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + assert_period ~expected_kind:Promotion b __LOC__ + (* bake_until_first_block_of_next_period ~offset:1l b + * >>=? fun b -> + * assert_period ~expected_kind:Promotion b __LOC__ *) + >>=? fun () -> + Context.Vote.get_participation_ema b + >>=? fun initial_participation_ema -> + (* beginning of promotion period, denoted by _p4; + take a snapshot of the active delegates and their rolls from listings *) + get_delegates_and_rolls_from_listings b + >>=? fun (delegates_p4, rolls_p4) -> + Context.Vote.get_participation_ema b + >>=? fun participation_ema -> + get_smallest_prefix_voters_for_quorum delegates_p4 rolls_p4 participation_ema + |> fun voters -> + (* take the first voter out so there cannot be quorum *) + let voters_without_quorum = + WithExceptions.Option.get ~loc:__LOC__ @@ List.tl voters + in + get_rolls b voters_without_quorum __LOC__ + >>=? fun voter_rolls -> + (* all voters_without_quorum vote, for yays; + no nays, so supermajority is satisfied *) + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + voters_without_quorum + >>=? fun operations -> + Block.bake ~operations b + >>=? fun b -> + (* skip to end of promotion period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + get_expected_participation_ema rolls_p4 voter_rolls initial_participation_ema + |> fun expected_participation_ema -> + Context.Vote.get_participation_ema b + >>=? fun new_participation_ema -> + (* assert the formula to calculate participation_ema is correct *) + Assert.equal_int + ~loc:__LOC__ + expected_participation_ema + (Int32.to_int new_participation_ema) + >>=? fun () -> + (* we move back to the proposal period because not enough quorum *) + assert_period ~expected_kind:Proposal b __LOC__ + >>=? fun () -> + assert_listings_not_empty b ~loc:__LOC__ >>=? fun () -> return_unit + +(** Identical proposals (identified by their hash) must be counted as + one. *) +let test_multiple_identical_proposals_count_as_one () = + Context.init 1 + >>=? fun (b, delegates) -> + assert_period ~expected_kind:Proposal b __LOC__ + >>=? fun () -> + let proposer = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd delegates in + Op.proposals (B b) proposer [Protocol_hash.zero; Protocol_hash.zero] + >>=? fun ops -> + Block.bake ~operations:[ops] b + >>=? fun b -> + (* compute the weight of proposals *) + Context.Vote.get_proposals (B b) + >>=? fun ps -> + (* compute the rolls of proposer *) + Context.Contract.pkh proposer + >>=? fun pkh -> + Context.Vote.get_listings (B b) + >>=? fun l -> + ( match List.find_opt (fun (del, _) -> del = pkh) l with + | None -> + failwith "%s - Missing delegate" __LOC__ + | Some (_, proposer_rolls) -> + return proposer_rolls ) + >>=? fun proposer_rolls -> + (* correctly count the double proposal for zero as one proposal *) + let expected_weight_proposer = proposer_rolls in + match Environment.Protocol_hash.(Map.find_opt zero ps) with + | Some v -> + if v = expected_weight_proposer then return_unit + else + failwith + "%s - Wrong count %ld is not %ld; identical proposals count as one" + __LOC__ + v + expected_weight_proposer + | None -> + failwith "%s - Missing proposal" __LOC__ + +(** Assume the initial balance of allocated by Context.init is at + least 4 times the value of the tokens_per_roll constant. *) +let test_supermajority_in_proposal there_is_a_winner () = + let min_proposal_quorum = 0l in + Context.init ~min_proposal_quorum ~initial_balances:[1L; 1L; 1L] 10 + >>=? fun (b, delegates) -> + Context.get_constants (B b) + >>=? fun { parametric = + {blocks_per_cycle; tokens_per_roll; blocks_per_voting_period; _}; + _ } -> + let del1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 in + let del2 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 1 in + let del3 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 2 in + List.map_es (fun del -> Context.Contract.pkh del) [del1; del2; del3] + >>=? fun pkhs -> + let policy = Block.Excluding pkhs in + Op.transaction + (B b) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 3) + del1 + tokens_per_roll + >>=? fun op1 -> + Op.transaction + (B b) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 4) + del2 + tokens_per_roll + >>=? fun op2 -> + ( if there_is_a_winner then Test_tez.Tez.( *? ) tokens_per_roll 3L + else Test_tez.Tez.( *? ) tokens_per_roll 2L ) + >>?= fun bal3 -> + Op.transaction + (B b) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 5) + del3 + bal3 + >>=? fun op3 -> + Block.bake ~policy ~operations:[op1; op2; op3] b + >>=? fun b -> + (* we let one voting period pass; we make sure that: + - the three selected delegates remain active by re-registering as delegates + - their number of rolls do not change *) + List.fold_left_es + (fun b _ -> + List.map_es + (fun del -> + Context.Contract.pkh del + >>=? fun pkh -> Op.delegation (B b) del (Some pkh)) + delegates + >>=? fun ops -> + Block.bake ~policy ~operations:ops b + >>=? fun b -> Block.bake_until_cycle_end ~policy b) + b + (1 -- Int32.to_int (Int32.div blocks_per_voting_period blocks_per_cycle)) + >>=? fun b -> + (* make the proposals *) + Op.proposals (B b) del1 [protos.(0)] + >>=? fun ops1 -> + Op.proposals (B b) del2 [protos.(0)] + >>=? fun ops2 -> + Op.proposals (B b) del3 [protos.(1)] + >>=? fun ops3 -> + Block.bake ~policy ~operations:[ops1; ops2; ops3] b + >>=? fun b -> + bake_until_first_block_of_next_period b + >>=? fun b -> + (* we remain in the proposal period when there is no winner, + otherwise we move to the exploration period *) + ( if there_is_a_winner then assert_period ~expected_kind:Exploration b __LOC__ + else assert_period ~expected_kind:Proposal b __LOC__ ) + >>=? fun () -> return_unit + +(** After one voting period, if [has_quorum] then the period kind must + have been the cooldown vote. Otherwise, it should have remained in + place in the proposal period. *) +let test_quorum_in_proposal has_quorum () = + let total_tokens = 32_000_000_000_000L in + let half_tokens = Int64.div total_tokens 2L in + Context.init ~initial_balances:[1L; half_tokens; half_tokens] 3 + >>=? fun (b, delegates) -> + Context.get_constants (B b) + >>=? fun { parametric = + { blocks_per_cycle; + min_proposal_quorum; + blocks_per_voting_period; + _ }; + _ } -> + let del1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 in + let del2 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 1 in + List.map_es (fun del -> Context.Contract.pkh del) [del1; del2] + >>=? fun pkhs -> + let policy = Block.Excluding pkhs in + let quorum = + if has_quorum then Int64.of_int32 min_proposal_quorum + else Int64.(sub (of_int32 min_proposal_quorum) 10L) + in + let bal = + Int64.(div (mul total_tokens quorum) 100_00L) |> Test_tez.Tez.of_mutez_exn + in + Op.transaction (B b) del2 del1 bal + >>=? fun op2 -> + Block.bake ~policy ~operations:[op2] b + >>=? fun b -> + (* we let one voting period pass; we make sure that: + - the two selected delegates remain active by re-registering as delegates + - their number of rolls do not change *) + List.fold_left_es + (fun b _ -> + List.map_es + (fun del -> + Context.Contract.pkh del + >>=? fun pkh -> Op.delegation (B b) del (Some pkh)) + [del1; del2] + >>=? fun ops -> + Block.bake ~policy ~operations:ops b + >>=? fun b -> Block.bake_until_cycle_end ~policy b) + b + (1 -- Int32.to_int (Int32.div blocks_per_voting_period blocks_per_cycle)) + >>=? fun b -> + (* make the proposal *) + Op.proposals (B b) del1 [protos.(0)] + >>=? fun ops -> + Block.bake ~policy ~operations:[ops] b + >>=? fun b -> + bake_until_first_block_of_next_period b + >>=? fun b -> + (* we remain in the proposal period when there is no quorum, + otherwise we move to the cooldown vote period *) + ( if has_quorum then assert_period ~expected_kind:Exploration b __LOC__ + else assert_period ~expected_kind:Proposal b __LOC__ ) + >>=? fun () -> return_unit + +(** If a supermajority is reached, then the voting period must be + reached. Otherwise, it remains in proposal period. *) +let test_supermajority_in_exploration supermajority () = + let min_proposal_quorum = Int32.(of_int @@ (100_00 / 100)) in + Context.init ~min_proposal_quorum 100 + >>=? fun (b, delegates) -> + let del1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 in + let proposal = protos.(0) in + Op.proposals (B b) del1 [proposal] + >>=? fun ops1 -> + Block.bake ~operations:[ops1] b + >>=? fun b -> + bake_until_first_block_of_next_period b + >>=? fun b -> + (* move to exploration *) + assert_period ~expected_kind:Exploration b __LOC__ + >>=? fun () -> + (* assert our proposal won *) + Context.Vote.get_current_proposal (B b) + >>=? (function + | Some v -> + if Protocol_hash.(equal proposal v) then return_unit + else failwith "%s - Wrong proposal" __LOC__ + | None -> + failwith "%s - Missing proposal" __LOC__) + >>=? fun () -> + (* beginning of exploration period, denoted by _p2; + take a snapshot of the active delegates and their rolls from listings *) + get_delegates_and_rolls_from_listings b + >>=? fun (delegates_p2, _rolls_p2) -> + (* supermajority means [num_yays / (num_yays + num_nays) >= s_num / s_den], + which is equivalent with [num_yays >= num_nays * s_num / (s_den - s_num)] *) + let num_delegates = List.length delegates_p2 in + let num_nays = num_delegates / 5 in + (* any smaller number will do as well *) + let num_yays = num_nays * s_num / (s_den - s_num) in + (* majority/minority vote depending on the [supermajority] parameter *) + let num_yays = if supermajority then num_yays else num_yays - 1 in + let open Alpha_context in + let (nays_delegates, rest) = List.split_n num_nays delegates_p2 in + let (yays_delegates, _) = List.split_n num_yays rest in + List.map_es (fun del -> Op.ballot (B b) del proposal Vote.Yay) yays_delegates + >>=? fun operations_yays -> + List.map_es (fun del -> Op.ballot (B b) del proposal Vote.Nay) nays_delegates + >>=? fun operations_nays -> + let operations = operations_yays @ operations_nays in + Block.bake ~operations b + >>=? fun b -> + bake_until_first_block_of_next_period b + >>=? fun b -> + ( if supermajority then assert_period ~expected_kind:Cooldown b __LOC__ + else assert_period ~expected_kind:Proposal b __LOC__ ) + >>=? fun () -> return_unit + +(** Test also how the selection scales: all delegates propose max + proposals. *) +let test_no_winning_proposal num_delegates () = + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + Context.init ~min_proposal_quorum num_delegates + >>=? fun (b, _) -> + (* beginning of proposal, denoted by _p1; + take a snapshot of the active delegates and their rolls from listings *) + get_delegates_and_rolls_from_listings b + >>=? fun (delegates_p1, _rolls_p1) -> + let open Alpha_context in + let props = + List.map (fun i -> protos.(i)) (1 -- Constants.max_proposals_per_delegate) + in + (* all delegates active in p1 propose the same proposals *) + List.map_es (fun del -> Op.proposals (B b) del props) delegates_p1 + >>=? fun ops_list -> + Block.bake ~operations:ops_list b + >>=? fun b -> + (* skip to exploration period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* we stay in the same proposal period because no winning proposal *) + assert_period ~expected_kind:Proposal b __LOC__ >>=? fun () -> return_unit + +(** Vote to pass with maximum possible participation_ema (100%), it is + sufficient for the vote quorum to be equal or greater than the + maximum quorum cap. *) +let test_quorum_capped_maximum num_delegates () = + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + Context.init ~min_proposal_quorum num_delegates + >>=? fun (b, delegates) -> + (* set the participation EMA to 100% *) + Context.Vote.set_participation_ema b 100_00l + >>= fun b -> + Context.get_constants (B b) + >>=? fun {parametric = {quorum_max; _}; _} -> + (* proposal period *) + let open Alpha_context in + assert_period ~expected_kind:Proposal b __LOC__ + >>=? fun () -> + (* propose a new protocol *) + let protocol = Protocol_hash.zero in + let proposer = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 + in + Op.proposals (B b) proposer [protocol] + >>=? fun ops -> + Block.bake ~operations:[ops] b + >>=? fun b -> + (* skip to exploration period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* we moved to an exploration period with one proposal *) + assert_period ~expected_kind:Exploration b __LOC__ + >>=? fun () -> + (* take percentage of the delegates equal or greater than quorum_max *) + let minimum_to_pass = + Float.of_int (List.length delegates) + *. Int32.(to_float quorum_max) + /. 100_00. + |> Float.ceil |> Float.to_int + in + let voters = List.take_n minimum_to_pass delegates in + (* all voters vote for yays; no nays, so supermajority is satisfied *) + List.map_es (fun del -> Op.ballot (B b) del protocol Vote.Yay) voters + >>=? fun operations -> + Block.bake ~operations b + >>=? fun b -> + (* skip to next period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* expect to move to cooldown because we have supermajority and enough quorum *) + assert_period ~expected_kind:Cooldown b __LOC__ + +(** Vote to pass with minimum possible participation_ema (0%), it is + sufficient for the vote quorum to be equal or greater than the + minimum quorum cap. *) +let test_quorum_capped_minimum num_delegates () = + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + Context.init ~min_proposal_quorum num_delegates + >>=? fun (b, delegates) -> + (* set the participation EMA to 0% *) + Context.Vote.set_participation_ema b 0l + >>= fun b -> + Context.get_constants (B b) + >>=? fun {parametric = {quorum_min; _}; _} -> + (* proposal period *) + let open Alpha_context in + assert_period ~expected_kind:Proposal b __LOC__ + >>=? fun () -> + (* propose a new protocol *) + let protocol = Protocol_hash.zero in + let proposer = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 + in + Op.proposals (B b) proposer [protocol] + >>=? fun ops -> + Block.bake ~operations:[ops] b + >>=? fun b -> + (* skip to exploration period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* we moved to an exploration period with one proposal *) + assert_period ~expected_kind:Exploration b __LOC__ + >>=? fun () -> + (* take percentage of the delegates equal or greater than quorum_min *) + let minimum_to_pass = + Float.of_int (List.length delegates) + *. Int32.(to_float quorum_min) + /. 100_00. + |> Float.ceil |> Float.to_int + in + let voters = List.take_n minimum_to_pass delegates in + (* all voters vote for yays; no nays, so supermajority is satisfied *) + List.map_es (fun del -> Op.ballot (B b) del protocol Vote.Yay) voters + >>=? fun operations -> + Block.bake ~operations b + >>=? fun b -> + (* skip to next period *) + bake_until_first_block_of_next_period b + >>=? fun b -> + (* expect to move to cooldown because we have supermajority and enough quorum *) + assert_period ~expected_kind:Cooldown b __LOC__ + +(* gets the voting power *) +let get_voting_power block pkhash = + let ctxt = Context.B block in + Context.get_voting_power ctxt pkhash + +(** Test that the voting power changes if the balance between bakers changes + and the blockchain moves to the next voting period. It also checks that + the total voting power coincides with the addition of the voting powers + of bakers *) +let test_voting_power_updated_each_voting_period () = + let open Test_tez.Tez in + (* Create three accounts with different amounts *) + Context.init + ~initial_balances:[80_000_000_000L; 48_000_000_000L; 4_000_000_000_000L] + 3 + >>=? fun (block, contracts) -> + let con1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 in + let con2 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 1 in + let con3 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 2 in + (* Retrieve balance of con1 *) + Context.Contract.balance (B block) con1 + >>=? fun balance1 -> + Assert.equal_tez ~loc:__LOC__ balance1 (of_mutez_exn 80_000_000_000L) + >>=? fun _ -> + (* Retrieve balance of con2 *) + Context.Contract.balance (B block) con2 + >>=? fun balance2 -> + Assert.equal_tez ~loc:__LOC__ balance2 (of_mutez_exn 48_000_000_000L) + >>=? fun _ -> + (* Retrieve balance of con3 *) + Context.Contract.balance (B block) con3 + >>=? fun balance3 -> + (* Retrieve constants blocks_per_voting_period and tokens_per_roll *) + Context.get_constants (B block) + >>=? fun {parametric = {tokens_per_roll; _}; _} -> + (* Get the key hashes of the bakers *) + Context.get_bakers (B block) + >>=? fun bakers -> + (* [Context.init] and [Context.get_bakers] store the accounts in reversed orders *) + let baker1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth bakers 2 in + let baker2 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth bakers 1 in + let baker3 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth bakers 0 in + (* Auxiliary assert_voting_power *) + let assert_voting_power ~loc n block baker = + get_voting_power block baker + >>=? fun voting_power -> + Assert.equal_int ~loc n (Int32.to_int voting_power) + in + (* Auxiliary assert_total_voting_power *) + let assert_total_voting_power ~loc n block = + Context.get_total_voting_power (B block) + >>=? fun total_voting_power -> + Assert.equal_int ~loc n (Int32.to_int total_voting_power) + in + (* Assert voting power is equal to the balance divided by tokens_per_roll *) + let expected_power_of_baker_1 = + Int64.(to_int (div (to_mutez balance1) (to_mutez tokens_per_roll))) + in + assert_voting_power ~loc:__LOC__ expected_power_of_baker_1 block baker1 + >>=? fun _ -> + (* Assert voting power is equal to the balance divided by tokens_per_roll *) + let expected_power_of_baker_2 = + Int64.(to_int (div (to_mutez balance2) (to_mutez tokens_per_roll))) + in + assert_voting_power ~loc:__LOC__ expected_power_of_baker_2 block baker2 + >>=? fun _ -> + (* Assert total voting power *) + let expected_power_of_baker_3 = + Int64.(to_int (div (to_mutez balance3) (to_mutez tokens_per_roll))) + in + assert_total_voting_power + ~loc:__LOC__ + Int.( + add + (add expected_power_of_baker_1 expected_power_of_baker_2) + expected_power_of_baker_3) + block + >>=? fun _ -> + (* Create policy that excludes baker1 and baker2 from baking *) + let policy = Block.Excluding [baker1; baker2] in + (* Transfer tokens_per_roll * num_rolls from baker1 to baker2 *) + let num_rolls = 5L in + tokens_per_roll *? num_rolls + >>?= fun amount -> + Op.transaction (B block) con1 con2 amount + >>=? fun op -> + (* Bake the block containing the transaction *) + Block.bake ~policy ~operations:[op] block + >>=? fun block -> + (* Retrieve balance of con1 *) + Context.Contract.balance (B block) con1 + >>=? fun balance1 -> + (* Assert balance has changed by tokens_per_roll * num_rolls *) + tokens_per_roll *? num_rolls + >>?= fun rolls -> + of_mutez_exn 80_000_000_000L -? rolls + >>?= Assert.equal_tez ~loc:__LOC__ balance1 + >>=? fun _ -> + (* Retrieve balance of con2 *) + Context.Contract.balance (B block) con2 + >>=? fun balance2 -> + (* Assert balance has changed by tokens_per_roll * num_rolls *) + tokens_per_roll *? num_rolls + >>?= fun rolls -> + of_mutez_exn 48_000_000_000L +? rolls + >>?= Assert.equal_tez ~loc:__LOC__ balance2 + >>=? fun () -> + Block.bake block + >>=? fun block -> + (* Assert voting power (and total) remains the same before next voting period *) + assert_voting_power ~loc:__LOC__ expected_power_of_baker_1 block baker1 + >>=? fun () -> + assert_voting_power ~loc:__LOC__ expected_power_of_baker_2 block baker2 + >>=? fun () -> + assert_voting_power ~loc:__LOC__ expected_power_of_baker_3 block baker3 + >>=? fun () -> + assert_total_voting_power + ~loc:__LOC__ + Int.( + add + (add expected_power_of_baker_1 expected_power_of_baker_2) + expected_power_of_baker_3) + block + >>=? fun _ -> + bake_until_first_block_of_next_period block + >>=? fun block -> + (* Assert voting power of baker1 has decreased by num_rolls *) + let expected_power_of_baker_1 = + Int.sub expected_power_of_baker_1 (Int64.to_int num_rolls) + in + assert_voting_power ~loc:__LOC__ expected_power_of_baker_1 block baker1 + >>=? fun _ -> + (* Assert voting power of baker2 has increased by num_rolls *) + let expected_power_of_baker_2 = + Int.add expected_power_of_baker_2 (Int64.to_int num_rolls) + in + assert_voting_power ~loc:__LOC__ expected_power_of_baker_2 block baker2 + >>=? fun _ -> + (* Retrieve voting power of baker3 *) + get_voting_power block baker3 + >>=? fun power -> + let power_of_baker_3 = Int32.to_int power in + (* Assert total voting power *) + assert_total_voting_power + ~loc:__LOC__ + Int.( + add + (add expected_power_of_baker_1 expected_power_of_baker_2) + power_of_baker_3) + block + +let tests = + [ Test_services.tztest + "voting successful_vote" + `Quick + (test_successful_vote 137); + Test_services.tztest + "voting cooldown, not enough quorum" + `Quick + (test_not_enough_quorum_in_exploration 245); + Test_services.tztest + "voting promotion, not enough quorum" + `Quick + (test_not_enough_quorum_in_promotion 432); + Test_services.tztest + "voting counting double proposal" + `Quick + test_multiple_identical_proposals_count_as_one; + Test_services.tztest + "voting proposal, with supermajority" + `Quick + (test_supermajority_in_proposal true); + Test_services.tztest + "voting proposal, without supermajority" + `Quick + (test_supermajority_in_proposal false); + Test_services.tztest + "voting proposal, with quorum" + `Quick + (test_quorum_in_proposal true); + Test_services.tztest + "voting proposal, without quorum" + `Quick + (test_quorum_in_proposal false); + Test_services.tztest + "voting cooldown, with supermajority" + `Quick + (test_supermajority_in_exploration true); + Test_services.tztest + "voting cooldown, without supermajority" + `Quick + (test_supermajority_in_exploration false); + Test_services.tztest + "voting proposal, no winning proposal" + `Quick + (test_no_winning_proposal 400); + Test_services.tztest + "voting quorum, quorum capped maximum" + `Quick + (test_quorum_capped_maximum 400); + Test_services.tztest + "voting quorum, quorum capped minimum" + `Quick + (test_quorum_capped_minimum 401); + Test_services.tztest + "voting power updated in each voting period" + `Quick + test_voting_power_updated_each_voting_period ] diff --git a/src/proto_009_PsFLoren/lib_protocol/tez_repr.ml b/src/proto_009_PsFLoren/lib_protocol/tez_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..9938824679d15ea38ac116111fbb8e6dcd0933f9 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/tez_repr.ml @@ -0,0 +1,254 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let id = "tez" + +let name = "mutez" + +include Compare.Int64 (* invariant: positive *) + +type error += + | Addition_overflow of t * t (* `Temporary *) + | Subtraction_underflow of t * t (* `Temporary *) + | Multiplication_overflow of t * int64 (* `Temporary *) + | Negative_multiplicator of t * int64 (* `Temporary *) + | Invalid_divisor of t * int64 + +(* `Temporary *) + +let zero = 0L + +(* all other constant are defined from the value of one micro tez *) +let one_mutez = 1L + +let one_cent = Int64.mul one_mutez 10_000L + +let fifty_cents = Int64.mul one_cent 50L + +(* 1 tez = 100 cents = 1_000_000 mutez *) +let one = Int64.mul one_cent 100L + +let of_string s = + let triplets = function + | hd :: tl -> + let len = String.length hd in + Compare.Int.( + len <= 3 && len > 0 && List.for_all (fun s -> String.length s = 3) tl) + | [] -> + false + in + let integers s = triplets (String.split_on_char ',' s) in + let decimals s = + let l = String.split_on_char ',' s in + if Compare.Int.(List.length l > 2) then false else triplets (List.rev l) + in + let parse left right = + let remove_commas s = String.concat "" (String.split_on_char ',' s) in + let pad_to_six s = + let len = String.length s in + String.init 6 (fun i -> if Compare.Int.(i < len) then s.[i] else '0') + in + Int64.of_string_opt (remove_commas left ^ pad_to_six (remove_commas right)) + in + match String.split_on_char '.' s with + | [left; right] -> + if String.contains s ',' then + if integers left && decimals right then parse left right else None + else if + Compare.Int.(String.length right > 0) + && Compare.Int.(String.length right <= 6) + then parse left right + else None + | [left] -> + if (not (String.contains s ',')) || integers left then parse left "" + else None + | _ -> + None + +let pp ppf amount = + let mult_int = 1_000_000L in + let rec left ppf amount = + let (d, r) = (Int64.(div amount 1000L), Int64.(rem amount 1000L)) in + if d > 0L then Format.fprintf ppf "%a%03Ld" left d r + else Format.fprintf ppf "%Ld" r + in + let right ppf amount = + let triplet ppf v = + if Compare.Int.(v mod 10 > 0) then Format.fprintf ppf "%03d" v + else if Compare.Int.(v mod 100 > 0) then + Format.fprintf ppf "%02d" (v / 10) + else Format.fprintf ppf "%d" (v / 100) + in + let (hi, lo) = (amount / 1000, amount mod 1000) in + if Compare.Int.(lo = 0) then Format.fprintf ppf "%a" triplet hi + else Format.fprintf ppf "%03d%a" hi triplet lo + in + let (ints, decs) = + (Int64.(div amount mult_int), Int64.(to_int (rem amount mult_int))) + in + left ppf ints ; + if Compare.Int.(decs > 0) then Format.fprintf ppf ".%a" right decs + +let to_string t = Format.asprintf "%a" pp t + +let ( -? ) t1 t2 = + if t2 <= t1 then ok (Int64.sub t1 t2) + else error (Subtraction_underflow (t1, t2)) + +let ( +? ) t1 t2 = + let t = Int64.add t1 t2 in + if t < t1 then error (Addition_overflow (t1, t2)) else ok t + +let ( *? ) t m = + let open Compare.Int64 in + let open Int64 in + let rec step cur pow acc = + if cur = 0L then ok acc + else + pow +? pow + >>? fun npow -> + if logand cur 1L = 1L then + acc +? pow >>? fun nacc -> step (shift_right_logical cur 1) npow nacc + else step (shift_right_logical cur 1) npow acc + in + if m < 0L then error (Negative_multiplicator (t, m)) + else record_trace (Multiplication_overflow (t, m)) @@ step m t 0L + +let ( /? ) t d = + if d <= 0L then error (Invalid_divisor (t, d)) else ok (Int64.div t d) + +let mul_exn t m = + match t *? Int64.(of_int m) with + | Ok v -> + v + | Error _ -> + invalid_arg "mul_exn" + +let of_mutez t = if t < 0L then None else Some t + +let of_mutez_exn x = + match of_mutez x with None -> invalid_arg "Tez.of_mutez" | Some v -> v + +let to_int64 t = t + +let to_mutez t = t + +let encoding = + let open Data_encoding in + Data_encoding.def + name + (check_size 10 (conv Z.of_int64 (Json.wrap_error Z.to_int64) n)) + +let () = + let open Data_encoding in + register_error_kind + `Temporary + ~id:(id ^ ".addition_overflow") + ~title:("Overflowing " ^ id ^ " addition") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Overflowing addition of %a %s and %a %s" + pp + opa + id + pp + opb + id) + ~description:("An addition of two " ^ id ^ " amounts overflowed") + (obj1 (req "amounts" (tup2 encoding encoding))) + (function Addition_overflow (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Addition_overflow (a, b)) ; + register_error_kind + `Temporary + ~id:(id ^ ".subtraction_underflow") + ~title:("Underflowing " ^ id ^ " subtraction") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Underflowing subtraction of %a %s and %a %s" + pp + opa + id + pp + opb + id) + ~description:("An subtraction of two " ^ id ^ " amounts underflowed") + (obj1 (req "amounts" (tup2 encoding encoding))) + (function Subtraction_underflow (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Subtraction_underflow (a, b)) ; + register_error_kind + `Temporary + ~id:(id ^ ".multiplication_overflow") + ~title:("Overflowing " ^ id ^ " multiplication") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Overflowing multiplication of %a %s and %Ld" + pp + opa + id + opb) + ~description: + ("A multiplication of a " ^ id ^ " amount by an integer overflowed") + (obj2 (req "amount" encoding) (req "multiplicator" int64)) + (function Multiplication_overflow (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Multiplication_overflow (a, b)) ; + register_error_kind + `Temporary + ~id:(id ^ ".negative_multiplicator") + ~title:("Negative " ^ id ^ " multiplicator") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Multiplication of %a %s by negative integer %Ld" + pp + opa + id + opb) + ~description:("Multiplication of a " ^ id ^ " amount by a negative integer") + (obj2 (req "amount" encoding) (req "multiplicator" int64)) + (function Negative_multiplicator (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Negative_multiplicator (a, b)) ; + register_error_kind + `Temporary + ~id:(id ^ ".invalid_divisor") + ~title:("Invalid " ^ id ^ " divisor") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Division of %a %s by non positive integer %Ld" + pp + opa + id + opb) + ~description: + ("Multiplication of a " ^ id ^ " amount by a non positive integer") + (obj2 (req "amount" encoding) (req "divisor" int64)) + (function Invalid_divisor (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Invalid_divisor (a, b)) + +type tez = t diff --git a/src/proto_009_PsFLoren/lib_protocol/tez_repr.mli b/src/proto_009_PsFLoren/lib_protocol/tez_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..382439b10874bb2967278cf70c653ffdbcd5ca3b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/tez_repr.mli @@ -0,0 +1,71 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t + +type tez = t + +val zero : t + +val one_mutez : t + +val one_cent : t + +val fifty_cents : t + +val one : t + +val ( -? ) : t -> t -> t tzresult + +val ( +? ) : t -> t -> t tzresult + +val ( *? ) : t -> int64 -> t tzresult + +val ( /? ) : t -> int64 -> t tzresult + +val to_mutez : t -> int64 + +(** [of_mutez n] (micro tez) is None if n is negative *) +val of_mutez : int64 -> t option + +(** [of_mutez_exn n] fails if n is negative. + It should only be used at toplevel for constants. *) +val of_mutez_exn : int64 -> t + +(** It should only be used at toplevel for constants. *) +val mul_exn : t -> int -> t + +val encoding : t Data_encoding.t + +val to_int64 : t -> int64 + +include Compare.S with type t := t + +val pp : Format.formatter -> t -> unit + +val of_string : string -> t option + +val to_string : t -> string diff --git a/src/proto_009_PsFLoren/lib_protocol/tezos-embedded-protocol-009-PsFLoren.opam b/src/proto_009_PsFLoren/lib_protocol/tezos-embedded-protocol-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..42fb3a7b86f5ddb48c4e8962574095e5ccfec537 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/tezos-embedded-protocol-009-PsFLoren.opam @@ -0,0 +1,25 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "2.0" } + "tezos-protocol-009-PsFLoren" + "tezos-protocol-compiler" + "tezos-protocol-updater" +] +build: [ + [ + "%{tezos-protocol-compiler:lib}%/replace" + "%{tezos-protocol-compiler:lib}%/dune_protocol.template" + "dune" + "%{tezos-protocol-compiler:lib}%/final_protocol_versions" + "009_PsFLoren" + ] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: economic-protocol definition, embedded in `tezos-node`" diff --git a/src/proto_009_PsFLoren/lib_protocol/tezos-protocol-009-PsFLoren-tests.opam b/src/proto_009_PsFLoren/lib_protocol/tezos-protocol-009-PsFLoren-tests.opam new file mode 100644 index 0000000000000000000000000000000000000000..98645a730771d48ad2b2fbca3618bcce29d9aa2a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/tezos-protocol-009-PsFLoren-tests.opam @@ -0,0 +1,33 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "2.0" } + "tezos-protocol-compiler" + "alcotest-lwt" { with-test & >= "1.1.0" } + "astring" { with-test } + "crowbar" { with-test } + "tezos-009-PsFLoren-test-helpers" { with-test } + "tezos-stdlib-unix" { with-test } + "tezos-protocol-environment" { with-test } + "tezos-test-services" { with-test } + "tezos-client-base" { with-test } + "tezos-protocol-009-PsFLoren-parameters" { with-test } + "tezos-shell-services" { with-test } +] +build: [ + [ + "%{tezos-protocol-compiler:lib}%/replace" + "%{tezos-protocol-compiler:lib}%/dune_protocol.template" + "dune" + "%{tezos-protocol-compiler:lib}%/final_protocol_versions" + "009_PsFLoren" + ] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: tests for economic-protocol definition" diff --git a/src/proto_009_PsFLoren/lib_protocol/tezos-protocol-009-PsFLoren.opam b/src/proto_009_PsFLoren/lib_protocol/tezos-protocol-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..1fa315ce6f886c3e627faa9b38a6c15940b0c585 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/tezos-protocol-009-PsFLoren.opam @@ -0,0 +1,23 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "2.0" } + "tezos-protocol-compiler" +] +build: [ + [ + "%{tezos-protocol-compiler:lib}%/replace" + "%{tezos-protocol-compiler:lib}%/dune_protocol.template" + "dune" + "%{tezos-protocol-compiler:lib}%/final_protocol_versions" + "009_PsFLoren" + ] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: economic-protocol definition" diff --git a/src/proto_009_PsFLoren/lib_protocol/tezos-protocol-functor-009-PsFLoren.opam b/src/proto_009_PsFLoren/lib_protocol/tezos-protocol-functor-009-PsFLoren.opam new file mode 100644 index 0000000000000000000000000000000000000000..65ad3fa8e9f1dda6b3a5c41fa754a0debee12e11 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/tezos-protocol-functor-009-PsFLoren.opam @@ -0,0 +1,24 @@ +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "2.0" } + "tezos-protocol-009-PsFLoren" + "tezos-protocol-compiler" +] +build: [ + [ + "%{tezos-protocol-compiler:lib}%/replace" + "%{tezos-protocol-compiler:lib}%/dune_protocol.template" + "dune" + "%{tezos-protocol-compiler:lib}%/final_protocol_versions" + "009_PsFLoren" + ] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: economic-protocol definition parameterized by its environment implementation" diff --git a/src/proto_009_PsFLoren/lib_protocol/time_repr.ml b/src/proto_009_PsFLoren/lib_protocol/time_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..c9e529925772a7927e0131916b021e6ac4ac186a --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/time_repr.ml @@ -0,0 +1,64 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Time + +type time = t + +type error += Timestamp_add (* `Permanent *) + +type error += Timestamp_sub (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"timestamp_add" + ~title:"Timestamp add" + ~description:"Overflow when adding timestamps." + ~pp:(fun ppf () -> Format.fprintf ppf "Overflow when adding timestamps.") + Data_encoding.empty + (function Timestamp_add -> Some () | _ -> None) + (fun () -> Timestamp_add) ; + register_error_kind + `Permanent + ~id:"timestamp_sub" + ~title:"Timestamp sub" + ~description:"Subtracting timestamps resulted in negative period." + ~pp:(fun ppf () -> + Format.fprintf ppf "Subtracting timestamps resulted in negative period.") + Data_encoding.empty + (function Timestamp_sub -> Some () | _ -> None) + (fun () -> Timestamp_sub) + +let of_seconds_string s = Option.map of_seconds (Int64.of_string_opt s) + +let to_seconds_string s = Int64.to_string (to_seconds s) + +let pp = pp_hum + +let ( +? ) x y = + try ok (add x (Period_repr.to_seconds y)) with _exn -> error Timestamp_add + +let ( -? ) x y = record_trace Timestamp_sub (Period_repr.of_seconds (diff x y)) diff --git a/src/proto_009_PsFLoren/lib_protocol/time_repr.mli b/src/proto_009_PsFLoren/lib_protocol/time_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..5a0a4c5d9f170a6c327afd776d29d81bd23af539 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/time_repr.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include module type of struct + include Time +end + +type time = t + +val pp : Format.formatter -> t -> unit + +val of_seconds_string : string -> time option + +val to_seconds_string : time -> string + +val ( +? ) : time -> Period_repr.t -> time tzresult + +val ( -? ) : time -> time -> Period_repr.t tzresult diff --git a/src/proto_009_PsFLoren/lib_protocol/vote_repr.ml b/src/proto_009_PsFLoren/lib_protocol/vote_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..4fb0b82d9fefb8fd644a44e8792a0870f0418b53 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/vote_repr.ml @@ -0,0 +1,46 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type proposal = Protocol_hash.t + +type ballot = Yay | Nay | Pass + +let ballot_encoding = + let of_int8 = function + | 0 -> + Yay + | 1 -> + Nay + | 2 -> + Pass + | _ -> + invalid_arg "ballot_of_int8" + in + let to_int8 = function Yay -> 0 | Nay -> 1 | Pass -> 2 in + let open Data_encoding in + (* union *) + splitted + ~binary:(conv to_int8 of_int8 int8) + ~json:(string_enum [("yay", Yay); ("nay", Nay); ("pass", Pass)]) diff --git a/src/proto_009_PsFLoren/lib_protocol/vote_repr.mli b/src/proto_009_PsFLoren/lib_protocol/vote_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..8a7d4a59b68574ae6bdf136ff45ca954e95bab2b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/vote_repr.mli @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** a protocol change proposal *) +type proposal = Protocol_hash.t + +(** votes can be for, against or neutral. + Neutral serves to count towards a quorum *) +type ballot = Yay | Nay | Pass + +val ballot_encoding : ballot Data_encoding.t diff --git a/src/proto_009_PsFLoren/lib_protocol/vote_storage.ml b/src/proto_009_PsFLoren/lib_protocol/vote_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..ea2a5de4d1b86da040bba1d3e3fb76fbe24742cc --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/vote_storage.ml @@ -0,0 +1,173 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let recorded_proposal_count_for_delegate ctxt proposer = + Storage.Vote.Proposals_count.find ctxt proposer >|=? Option.value ~default:0 + +let record_proposal ctxt proposal proposer = + recorded_proposal_count_for_delegate ctxt proposer + >>=? fun count -> + Storage.Vote.Proposals_count.add ctxt proposer (count + 1) + >>= fun ctxt -> Storage.Vote.Proposals.add ctxt (proposal, proposer) >|= ok + +let get_proposals ctxt = + Storage.Vote.Proposals.fold + ctxt + ~init:(ok Protocol_hash.Map.empty) + ~f:(fun (proposal, delegate) acc -> + (* Assuming the same listings is used at votings *) + Storage.Vote.Listings.get ctxt delegate + >>=? fun weight -> + Lwt.return + ( acc + >|? fun acc -> + let previous = + match Protocol_hash.Map.find_opt proposal acc with + | None -> + 0l + | Some x -> + x + in + Protocol_hash.Map.add proposal (Int32.add weight previous) acc )) + +let clear_proposals ctxt = + Storage.Vote.Proposals_count.clear ctxt + >>= fun ctxt -> Storage.Vote.Proposals.clear ctxt + +type ballots = {yay : int32; nay : int32; pass : int32} + +let ballots_encoding = + let open Data_encoding in + conv + (fun {yay; nay; pass} -> (yay, nay, pass)) + (fun (yay, nay, pass) -> {yay; nay; pass}) + @@ obj3 (req "yay" int32) (req "nay" int32) (req "pass" int32) + +let has_recorded_ballot = Storage.Vote.Ballots.mem + +let record_ballot = Storage.Vote.Ballots.init + +let get_ballots ctxt = + Storage.Vote.Ballots.fold + ctxt + ~f:(fun delegate ballot (ballots : ballots tzresult) -> + (* Assuming the same listings is used at votings *) + Storage.Vote.Listings.get ctxt delegate + >>=? fun weight -> + let count = Int32.add weight in + Lwt.return + ( ballots + >|? fun ballots -> + match ballot with + | Yay -> + {ballots with yay = count ballots.yay} + | Nay -> + {ballots with nay = count ballots.nay} + | Pass -> + {ballots with pass = count ballots.pass} )) + ~init:(ok {yay = 0l; nay = 0l; pass = 0l}) + +let get_ballot_list = Storage.Vote.Ballots.bindings + +let clear_ballots = Storage.Vote.Ballots.clear + +let listings_encoding = + Data_encoding.( + list + (obj2 (req "pkh" Signature.Public_key_hash.encoding) (req "rolls" int32))) + +let update_listings ctxt = + Storage.Vote.Listings.clear ctxt + >>= fun ctxt -> + Roll_storage.fold ctxt (ctxt, 0l) ~f:(fun _roll delegate (ctxt, total) -> + (* TODO use snapshots *) + let delegate = Signature.Public_key.hash delegate in + Storage.Vote.Listings.find ctxt delegate + >|=? Option.value ~default:0l + >>=? fun count -> + Storage.Vote.Listings.add ctxt delegate (Int32.succ count) + >|= fun ctxt -> ok (ctxt, Int32.succ total)) + >>=? fun (ctxt, total) -> + Storage.Vote.Listings_size.add ctxt total >>= fun ctxt -> return ctxt + +let listing_size = Storage.Vote.Listings_size.get + +let in_listings = Storage.Vote.Listings.mem + +let get_listings = Storage.Vote.Listings.bindings + +let get_voting_power_free ctxt owner = + Storage.Vote.Listings.find ctxt owner >|=? Option.value ~default:0l + +(* This function bypasses the carbonated functors to account for gas consumption. + This is a temporary situation intended to be fixed by adding the right + carbonated functors in a future amendment *) +let get_voting_power ctxt owner = + let open Raw_context in + (* Always consume read access to memory *) + (* Accessing an int32 at /votes/listings/pkh *) + consume_gas ctxt (Storage_costs.read_access ~path_length:3 ~read_bytes:4) + >>?= fun ctxt -> + Storage.Vote.Listings.find ctxt owner + >|=? function None -> (ctxt, 0l) | Some power -> (ctxt, power) + +let get_total_voting_power_free = listing_size + +(* This function bypasses the carbonated functors to account for gas consumption. + This is a temporary situation intended to be fixed by adding the right + carbonated functors in a future amendment *) +let get_total_voting_power ctxt = + let open Raw_context in + (* Accessing an int32 at /votes/listings_size *) + consume_gas ctxt (Storage_costs.read_access ~path_length:2 ~read_bytes:4) + >>?= fun ctxt -> + get_total_voting_power_free ctxt + >|=? fun total_voting_power -> (ctxt, total_voting_power) + +let get_current_quorum ctxt = + Storage.Vote.Participation_ema.get ctxt + >|=? fun participation_ema -> + let quorum_min = Constants_storage.quorum_min ctxt in + let quorum_max = Constants_storage.quorum_max ctxt in + let quorum_diff = Int32.sub quorum_max quorum_min in + Int32.(add quorum_min (div (mul participation_ema quorum_diff) 100_00l)) + +let get_participation_ema = Storage.Vote.Participation_ema.get + +let set_participation_ema = Storage.Vote.Participation_ema.update + +let get_current_proposal = Storage.Vote.Current_proposal.get + +let find_current_proposal = Storage.Vote.Current_proposal.find + +let init_current_proposal = Storage.Vote.Current_proposal.init + +let clear_current_proposal = Storage.Vote.Current_proposal.remove_existing + +let init ctxt ~start_position = + (* participation EMA is in centile of a percentage *) + let participation_ema = Constants_storage.quorum_max ctxt in + Storage.Vote.Participation_ema.init ctxt participation_ema + >>=? fun ctxt -> Voting_period_storage.init_first_period ctxt ~start_position diff --git a/src/proto_009_PsFLoren/lib_protocol/vote_storage.mli b/src/proto_009_PsFLoren/lib_protocol/vote_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..5bfc0ae34eb55219345db99c3d319210024af21b --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/vote_storage.mli @@ -0,0 +1,116 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Manages all the voting related storage in Storage.Vote. *) + +(** Records a protocol proposal with the delegate that proposed it. *) +val record_proposal : + Raw_context.t -> + Protocol_hash.t -> + Signature.Public_key_hash.t -> + Raw_context.t tzresult Lwt.t + +val recorded_proposal_count_for_delegate : + Raw_context.t -> Signature.Public_key_hash.t -> int tzresult Lwt.t + +(** Computes for each proposal how many delegates proposed it. *) +val get_proposals : Raw_context.t -> int32 Protocol_hash.Map.t tzresult Lwt.t + +val clear_proposals : Raw_context.t -> Raw_context.t Lwt.t + +(** Counts of the votes *) +type ballots = {yay : int32; nay : int32; pass : int32} + +val ballots_encoding : ballots Data_encoding.t + +val has_recorded_ballot : + Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t + +(** Records a vote for a delegate, returns a {!Storage_error Existing_key} if + the vote was already registered *) +val record_ballot : + Raw_context.t -> + Signature.Public_key_hash.t -> + Vote_repr.ballot -> + Raw_context.t tzresult Lwt.t + +(** Computes the sum of the current ballots weighted by stake. *) +val get_ballots : Raw_context.t -> ballots tzresult Lwt.t + +val get_ballot_list : + Raw_context.t -> (Signature.Public_key_hash.t * Vote_repr.ballot) list Lwt.t + +val clear_ballots : Raw_context.t -> Raw_context.t Lwt.t + +val listings_encoding : + (Signature.Public_key_hash.t * int32) list Data_encoding.t + +(** Populates [!Storage.Vote.Listings] using the currently existing rolls and + sets Listings_size. Delegates without rolls are not included in the listing. *) +val update_listings : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Returns the sum of all rolls of all delegates. *) +val listing_size : Raw_context.t -> int32 tzresult Lwt.t + +(** Verifies the presence of a delegate in the listing. *) +val in_listings : Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t + +val get_listings : + Raw_context.t -> (Signature.Public_key_hash.t * int32) list Lwt.t + +val get_voting_power_free : + Raw_context.t -> Signature.public_key_hash -> int32 tzresult Lwt.t + +val get_voting_power : + Raw_context.t -> + Signature.public_key_hash -> + (Raw_context.t * int32) tzresult Lwt.t + +val get_total_voting_power_free : Raw_context.t -> int32 tzresult Lwt.t + +val get_total_voting_power : + Raw_context.t -> (Raw_context.t * int32) tzresult Lwt.t + +val get_current_quorum : Raw_context.t -> int32 tzresult Lwt.t + +val get_participation_ema : Raw_context.t -> int32 tzresult Lwt.t + +val set_participation_ema : + Raw_context.t -> int32 -> Raw_context.t tzresult Lwt.t + +val get_current_proposal : Raw_context.t -> Protocol_hash.t tzresult Lwt.t + +val find_current_proposal : + Raw_context.t -> Protocol_hash.t option tzresult Lwt.t + +val init_current_proposal : + Raw_context.t -> Protocol_hash.t -> Raw_context.t tzresult Lwt.t + +val clear_current_proposal : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Sets the initial quorum to 80% and period kind to proposal. *) +val init : + Raw_context.t -> start_position:Int32.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/voting_period_repr.ml b/src/proto_009_PsFLoren/lib_protocol/voting_period_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..886c12c55561c19980c6cb7708a59172db311723 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/voting_period_repr.ml @@ -0,0 +1,164 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type kind = Proposal | Exploration | Cooldown | Promotion | Adoption + +let string_of_kind = function + | Proposal -> + "proposal" + | Exploration -> + "exploration" + | Cooldown -> + "cooldown" + | Promotion -> + "promotion" + | Adoption -> + "adoption" + +let pp_kind ppf kind = Format.fprintf ppf "%s" @@ string_of_kind kind + +let kind_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ case + (Tag 0) + ~title:"Proposal" + (constant "proposal") + (function Proposal -> Some () | _ -> None) + (fun () -> Proposal); + case + (Tag 1) + ~title:"exploration" + (constant "exploration") + (function Exploration -> Some () | _ -> None) + (fun () -> Exploration); + case + (Tag 2) + ~title:"Cooldown" + (constant "cooldown") + (function Cooldown -> Some () | _ -> None) + (fun () -> Cooldown); + case + (Tag 3) + ~title:"Promotion" + (constant "promotion") + (function Promotion -> Some () | _ -> None) + (fun () -> Promotion); + case + (Tag 4) + ~title:"Adoption" + (constant "adoption") + (function Adoption -> Some () | _ -> None) + (fun () -> Adoption) ] + +let succ_kind = function + | Proposal -> + Exploration + | Exploration -> + Cooldown + | Cooldown -> + Promotion + | Promotion -> + Adoption + | Adoption -> + Proposal + +type voting_period = {index : int32; kind : kind; start_position : int32} + +type t = voting_period + +type info = {voting_period : t; position : int32; remaining : int32} + +let root ~start_position = {index = 0l; kind = Proposal; start_position} + +let pp ppf {index; kind; start_position} = + Format.fprintf + ppf + "@[index: %ld@ ,kind:%a@, start_position: %ld@]" + index + pp_kind + kind + start_position + +let pp_info ppf {voting_period; position; remaining} = + Format.fprintf + ppf + "@[voting_period: %a@ ,position:%ld@, remaining: %ld@]" + pp + voting_period + position + remaining + +let encoding = + let open Data_encoding in + conv + (fun {index; kind; start_position} -> (index, kind, start_position)) + (fun (index, kind, start_position) -> {index; kind; start_position}) + (obj3 + (req + "index" + ~description: + "The voting period's index. Starts at 0 with the first block of \ + protocol alpha." + int32) + (req "kind" kind_encoding) + (req "start_position" int32)) + +let info_encoding = + let open Data_encoding in + conv + (fun {voting_period; position; remaining} -> + (voting_period, position, remaining)) + (fun (voting_period, position, remaining) -> + {voting_period; position; remaining}) + (obj3 + (req "voting_period" encoding) + (req "position" int32) + (req "remaining" int32)) + +include Compare.Make (struct + type nonrec t = t + + let compare p p' = Compare.Int32.compare p.index p'.index +end) + +let reset period ~start_position = + let index = Int32.succ period.index in + let kind = Proposal in + {index; kind; start_position} + +let succ period ~start_position = + let index = Int32.succ period.index in + let kind = succ_kind period.kind in + {index; kind; start_position} + +let position_since (level : Level_repr.t) (voting_period : t) = + Int32.(sub level.level_position voting_period.start_position) + +let remaining_blocks (level : Level_repr.t) (voting_period : t) + ~blocks_per_voting_period = + let position = position_since level voting_period in + Int32.(sub blocks_per_voting_period (succ position)) diff --git a/src/proto_009_PsFLoren/lib_protocol/voting_period_repr.mli b/src/proto_009_PsFLoren/lib_protocol/voting_period_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..77cd893a372a05b96f80dd467304728b9d72c576 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/voting_period_repr.mli @@ -0,0 +1,75 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The voting period kinds are ordered as follows: + Proposal -> Testing_vote -> Testing -> Promotion -> Adoption. + This order is the one used be the function [succ] below. + *) +type kind = + | Proposal (** protocols can be proposed *) + | Exploration (** a proposal can be voted *) + | Cooldown (** a delay before the second vote of the Promotion period. *) + | Promotion (** activation can be voted *) + | Adoption (** a delay before activation *) + +val kind_encoding : kind Data_encoding.t + +(** A voting period can be of 5 kinds and is uniquely identified by a counter + since the root. *) +type voting_period = {index : Int32.t; kind : kind; start_position : Int32.t} + +type t = voting_period + +type info = {voting_period : t; position : Int32.t; remaining : Int32.t} + +val root : start_position:Int32.t -> t + +include Compare.S with type t := voting_period + +val encoding : t Data_encoding.t + +val info_encoding : info Data_encoding.t + +val pp : Format.formatter -> t -> unit + +val pp_info : Format.formatter -> info -> unit + +val pp_kind : Format.formatter -> kind -> unit + +(** [reset period ~start_position] increment the index by one and set the kind + to Proposal which is the period kind that start the voting + process. [start_position] is the level at wich this voting_period started. +*) +val reset : t -> start_position:Int32.t -> t + +(** [succ period ~start_position] increment the index by one and set the kind to + its successor. [start_position] is the level at which this voting_period + started. *) +val succ : t -> start_position:Int32.t -> t + +val position_since : Level_repr.t -> t -> Int32.t + +val remaining_blocks : + Level_repr.t -> t -> blocks_per_voting_period:Int32.t -> Int32.t diff --git a/src/proto_009_PsFLoren/lib_protocol/voting_period_storage.ml b/src/proto_009_PsFLoren/lib_protocol/voting_period_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..85f0a0eb5dcb44dd70ceeee49424c0df6c4bade4 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/voting_period_storage.ml @@ -0,0 +1,189 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* + The shell uses the convention that a context at level n is the resulting + context of the application of block n. + Therefore when using an RPC on the last level of a voting period, the context + that is inspected is the resulting one. + + However [Amendment.may_start_new_voting_period] is run at the end of voting + period and it has to prepare the context for validating operations of the next + period. This causes the counter-intuitive result that the info returned by RPCs + at last level of a voting period mention data of the next voting period. + + For example, when validating the last block of a proposal period at level n + we have: + - Input context: + + voting_period = { kind = Proposal; + index = i; + start_position = n - blocks_per_voting_period} + + - position = n - start_position = blocks_per_voting_period + - remaining = blocks_per_voting_period - (position + 1) = 0 + + - Output context: + + voting_period = { kind = Exploration; + index = i + 1; + start_position = n + 1} + + Now if we calculate position and remaining in the voting period we get + strange results: + - position = n - (n + 1) = -1 + - remaining = blocks_per_voting_period + + In order to have the correct value for the RPCs a fix has been applied in + [voting_service] by calling a specific function + [voting_period_storage.get_rpc_fixed_current_info]. + + This odd behaviour could be fixed if [Amendment.may_start_new_voting_period] + was called when we start validating a block instead that at the end. + This should be carefully done because the voting period listing depends on + the rolls and it might break some invariant. + + When this is implemented one should: + - remove the function [voting_period_storage.get_rpc_fixed_current_info] + - edit the function [reset_current] and [inc_current] to use the + current level and not the next one. + - remove the storage for pred_kind + - make Voting_period_repr.t abstract + + You can also look at the MR description here: + https://gitlab.com/metastatedev/tezos/-/merge_requests/333 + *) + +let set_current = Storage.Vote.Current_period.update + +let get_current = Storage.Vote.Current_period.get + +let init = Storage.Vote.Current_period.init + +let init_first_period ctxt ~start_position = + init ctxt @@ Voting_period_repr.root ~start_position + >>=? fun ctxt -> + Storage.Vote.Pred_period_kind.init ctxt Voting_period_repr.Proposal + +let common ctxt = + get_current ctxt + >>=? fun current_period -> + Storage.Vote.Pred_period_kind.update ctxt current_period.kind + >|=? fun ctxt -> + let start_position = + (* because we are preparing the voting period for the next block we need to + use the next level. *) + Int32.succ (Level_storage.current ctxt).level_position + in + (ctxt, current_period, start_position) + +let reset ctxt = + common ctxt + >>=? fun (ctxt, current_period, start_position) -> + Voting_period_repr.reset current_period ~start_position |> set_current ctxt + +let succ ctxt = + common ctxt + >>=? fun (ctxt, current_period, start_position) -> + Voting_period_repr.succ current_period ~start_position |> set_current ctxt + +let get_current_kind ctxt = get_current ctxt >|=? fun {kind; _} -> kind + +let get_current_info ctxt = + get_current ctxt + >|=? fun voting_period -> + let blocks_per_voting_period = + Constants_storage.blocks_per_voting_period ctxt + in + let level = Level_storage.current ctxt in + let position = Voting_period_repr.position_since level voting_period in + let remaining = + Voting_period_repr.remaining_blocks + level + voting_period + blocks_per_voting_period + in + Voting_period_repr.{voting_period; position; remaining} + +let get_current_remaining ctxt = + get_current ctxt + >|=? fun voting_period -> + let blocks_per_voting_period = + Constants_storage.blocks_per_voting_period ctxt + in + Voting_period_repr.remaining_blocks + (Level_storage.current ctxt) + voting_period + blocks_per_voting_period + +let is_last_block ctxt = + get_current_remaining ctxt + >|=? fun remaining -> Compare.Int32.(remaining = 0l) + +let get_rpc_fixed_current_info ctxt = + get_current_info ctxt + >>=? fun ({voting_period; position; _} as voting_period_info) -> + if Compare.Int32.(position = Int32.minus_one) then + let level = Level_storage.current ctxt in + let blocks_per_voting_period = + Constants_storage.blocks_per_voting_period ctxt + in + Storage.Vote.Pred_period_kind.get ctxt + >|=? fun pred_kind -> + let voting_period : Voting_period_repr.t = + { + index = Int32.pred voting_period.index; + kind = pred_kind; + start_position = + Int32.(sub voting_period.start_position blocks_per_voting_period); + } + in + let position = Voting_period_repr.position_since level voting_period in + let remaining = + Voting_period_repr.remaining_blocks + level + voting_period + ~blocks_per_voting_period + in + ({voting_period; remaining; position} : Voting_period_repr.info) + else return voting_period_info + +let get_rpc_fixed_succ_info ctxt = + get_current ctxt + >|=? fun voting_period -> + let blocks_per_voting_period = + Constants_storage.blocks_per_voting_period ctxt + in + let level = + Level_storage.from_raw ctxt ~offset:1l (Level_storage.current ctxt).level + in + let position = Voting_period_repr.position_since level voting_period in + let remaining = + Voting_period_repr.remaining_blocks + level + voting_period + blocks_per_voting_period + in + Voting_period_repr.{voting_period; position; remaining} diff --git a/src/proto_009_PsFLoren/lib_protocol/voting_period_storage.mli b/src/proto_009_PsFLoren/lib_protocol/voting_period_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..1c457f5dcfc5365233d26a832cab0f0df4d199cb --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/voting_period_storage.mli @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val init : + Raw_context.t -> Voting_period_repr.t -> Raw_context.t tzresult Lwt.t + +(** Sets the initial period to [{voting_period = root; kind = Proposal; + start_position}]. *) +val init_first_period : + Raw_context.t -> start_position:Int32.t -> Raw_context.t tzresult Lwt.t + +(** Increment the index by one and set the kind to Proposal. *) +val reset : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Increment the index by one and set the kind to its successor. *) +val succ : Raw_context.t -> Raw_context.t tzresult Lwt.t + +val get_current : Raw_context.t -> Voting_period_repr.t tzresult Lwt.t + +val get_current_kind : Raw_context.t -> Voting_period_repr.kind tzresult Lwt.t + +(** Returns true if the context level is the last of current voting period. *) +val is_last_block : Raw_context.t -> bool tzresult Lwt.t + +(* Given the issue explained in voting_period_storage.ml this function behaves + currectly during the validation of a block but returns inconsistent info if + called after the finalization of the block. + For this reason when used by the RPC `votes/current_period_kind` gives an + unintuitive result: after the validation of the last block of a voting period + (e.g. proposal), it returns the kind of the next period (e.g. exploration). + To fix this, at least part of the current vote finalization should be moved + at the beginning of the block validation. + For retro-compatibility, we keep this function but we provide two new fixed + functions to reply correctly to RPCs [get_rpc_fixed_current_info] and + [get_rpc_fixed_succ_info]. *) +val get_current_info : Raw_context.t -> Voting_period_repr.info tzresult Lwt.t + +(* In order to avoid the problem of `get_current_info` explained above, this + function provides the corrent behavior for the new RPC `votes/current_period`. +*) +val get_rpc_fixed_current_info : + Raw_context.t -> Voting_period_repr.info tzresult Lwt.t + +(* In order to avoid the problem of `get_current_info` explained above, this + function provides the corrent behavior for the new RPC `votes/successor_period`. +*) +val get_rpc_fixed_succ_info : + Raw_context.t -> Voting_period_repr.info tzresult Lwt.t diff --git a/src/proto_009_PsFLoren/lib_protocol/voting_services.ml b/src/proto_009_PsFLoren/lib_protocol/voting_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..1460d3e31e5b56fef204b758729fcda2f4044331 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/voting_services.ml @@ -0,0 +1,156 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +module S = struct + let path = RPC_path.(open_root / "votes") + + let ballots = + RPC_service.get_service + ~description:"Sum of ballots casted so far during a voting period." + ~query:RPC_query.empty + ~output:Vote.ballots_encoding + RPC_path.(path / "ballots") + + let ballot_list = + RPC_service.get_service + ~description:"Ballots casted so far during a voting period." + ~query:RPC_query.empty + ~output: + Data_encoding.( + list + (obj2 + (req "pkh" Signature.Public_key_hash.encoding) + (req "ballot" Vote.ballot_encoding))) + RPC_path.(path / "ballot_list") + + let current_period = + RPC_service.get_service + ~description: + "Returns the voting period (index, kind, starting position) and \ + related information (position, remaining) of the interrogated block." + ~query:RPC_query.empty + ~output:Voting_period.info_encoding + RPC_path.(path / "current_period") + + let successor_period = + RPC_service.get_service + ~description: + "Returns the voting period (index, kind, starting position) and \ + related information (position, remaining) of the next block." + ~query:RPC_query.empty + ~output:Voting_period.info_encoding + RPC_path.(path / "successor_period") + + let current_period_kind_deprecated = + RPC_service.get_service + ~description: + "Current period kind. This RPC is DEPRECATED: use \ + `../votes/current_period` RPC instead." + ~query:RPC_query.empty + ~output:Voting_period.kind_encoding + RPC_path.(path / "current_period_kind") + + let current_quorum = + RPC_service.get_service + ~description:"Current expected quorum." + ~query:RPC_query.empty + ~output:Data_encoding.int32 + RPC_path.(path / "current_quorum") + + let listings = + RPC_service.get_service + ~description: + "List of delegates with their voting weight, in number of rolls." + ~query:RPC_query.empty + ~output:Vote.listings_encoding + RPC_path.(path / "listings") + + let proposals = + RPC_service.get_service + ~description:"List of proposals with number of supporters." + ~query:RPC_query.empty + ~output:(Protocol_hash.Map.encoding Data_encoding.int32) + RPC_path.(path / "proposals") + + let current_proposal = + RPC_service.get_service + ~description:"Current proposal under evaluation." + ~query:RPC_query.empty + ~output:(Data_encoding.option Protocol_hash.encoding) + RPC_path.(path / "current_proposal") + + let total_voting_power = + RPC_service.get_service + ~description: + "Total number of rolls for the delegates in the voting listings." + ~query:RPC_query.empty + ~output:Data_encoding.int32 + RPC_path.(path / "total_voting_power") +end + +let register () = + let open Services_registration in + register0 S.ballots (fun ctxt () () -> Vote.get_ballots ctxt) ; + register0 S.ballot_list (fun ctxt () () -> Vote.get_ballot_list ctxt >|= ok) ; + register0 S.current_period (fun ctxt () () -> + Voting_period.get_rpc_fixed_current_info ctxt) ; + register0 S.successor_period (fun ctxt () () -> + Voting_period.get_rpc_fixed_succ_info ctxt) ; + register0 S.current_period_kind_deprecated (fun ctxt () () -> + Voting_period.get_current_info ctxt + >|=? fun {voting_period; _} -> voting_period.kind) ; + register0 S.current_quorum (fun ctxt () () -> Vote.get_current_quorum ctxt) ; + register0 S.proposals (fun ctxt () () -> Vote.get_proposals ctxt) ; + register0 S.listings (fun ctxt () () -> Vote.get_listings ctxt >|= ok) ; + register0 S.current_proposal (fun ctxt () () -> + Vote.find_current_proposal ctxt) ; + register0 S.total_voting_power (fun ctxt () () -> + Vote.get_total_voting_power_free ctxt) + +let ballots ctxt block = RPC_context.make_call0 S.ballots ctxt block () () + +let ballot_list ctxt block = + RPC_context.make_call0 S.ballot_list ctxt block () () + +let current_period ctxt block = + RPC_context.make_call0 S.current_period ctxt block () () + +let successor_period ctxt block = + RPC_context.make_call0 S.successor_period ctxt block () () + +let current_quorum ctxt block = + RPC_context.make_call0 S.current_quorum ctxt block () () + +let listings ctxt block = RPC_context.make_call0 S.listings ctxt block () () + +let proposals ctxt block = RPC_context.make_call0 S.proposals ctxt block () () + +let current_proposal ctxt block = + RPC_context.make_call0 S.current_proposal ctxt block () () + +let total_voting_power ctxt block = + RPC_context.make_call0 S.total_voting_power ctxt block () () diff --git a/src/proto_009_PsFLoren/lib_protocol/voting_services.mli b/src/proto_009_PsFLoren/lib_protocol/voting_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..d56157aa6c1ae1631fab288debcdeb22c83373e0 --- /dev/null +++ b/src/proto_009_PsFLoren/lib_protocol/voting_services.mli @@ -0,0 +1,60 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +val ballots : 'a #RPC_context.simple -> 'a -> Vote.ballots shell_tzresult Lwt.t + +val ballot_list : + 'a #RPC_context.simple -> + 'a -> + (Signature.Public_key_hash.t * Vote.ballot) list shell_tzresult Lwt.t + +val current_period : + 'a #RPC_context.simple -> 'a -> Voting_period.info shell_tzresult Lwt.t + +val successor_period : + 'a #RPC_context.simple -> 'a -> Voting_period.info shell_tzresult Lwt.t + +val current_quorum : + 'a #RPC_context.simple -> 'a -> Int32.t shell_tzresult Lwt.t + +val listings : + 'a #RPC_context.simple -> + 'a -> + (Signature.Public_key_hash.t * int32) list shell_tzresult Lwt.t + +val proposals : + 'a #RPC_context.simple -> + 'a -> + Int32.t Protocol_hash.Map.t shell_tzresult Lwt.t + +val current_proposal : + 'a #RPC_context.simple -> 'a -> Protocol_hash.t option shell_tzresult Lwt.t + +val register : unit -> unit + +val total_voting_power : + 'a #RPC_context.simple -> 'a -> Int32.t shell_tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/main.ml b/src/proto_alpha/lib_protocol/main.ml index f49c7486920200d6cbfa21935f96672ac61de108..1439a430f337daeb8433ee7f0363fe32e2a58bbe 100644 --- a/src/proto_alpha/lib_protocol/main.ml +++ b/src/proto_alpha/lib_protocol/main.ml @@ -414,3 +414,5 @@ let init ctxt block_header = in Alpha_context.prepare_first_block ~typecheck ~level ~timestamp ~fitness ctxt >|=? fun ctxt -> Alpha_context.finalize ctxt + +(* Vanity nonce: 0000006957234545 *) diff --git a/tests_python/contracts_009/attic/accounts.tz b/tests_python/contracts_009/attic/accounts.tz new file mode 100644 index 0000000000000000000000000000000000000000..904a003f4f603685d500f5047e289162336c4695 --- /dev/null +++ b/tests_python/contracts_009/attic/accounts.tz @@ -0,0 +1,54 @@ +# This is a very simple accounts system. +# (Left key) initializes or deposits into an account +# (Right key (pair mutez (signed mutez))) withdraws mutez amount to a +# IMPLICIT_ACCOUNT created from the key if the balance is available +# and the key is correctly signed +parameter (or (key_hash %Initialize) + (pair %Withdraw + (key %from) + (pair + (mutez %withdraw_amount) + (signature %sig)))); +# Maps the key to the balance they have stored +storage (map :stored_balance key_hash mutez); +code { DUP; CAR; + # Deposit into account + IF_LEFT { DUP; DIIP{ CDR %stored_balance; DUP }; + DIP{ SWAP }; GET @opt_prev_balance; + # Create the account + IF_SOME # Add to an existing account + { RENAME @previous_balance; + AMOUNT; ADD; SOME; SWAP; UPDATE; NIL operation; PAIR } + { DIP{ AMOUNT; SOME }; UPDATE; NIL operation; PAIR }} + # Withdrawal + { DUP; DUP; DUP; DUP; + # Check signature on data + CAR %from; + DIIP{ CDAR %withdraw_amount; PACK ; BLAKE2B @signed_amount }; + DIP{ CDDR %sig }; CHECK_SIGNATURE; + IF {} { PUSH string "Bad signature"; FAILWITH }; + # Get user account information + DIIP{ CDR %stored_balance; DUP }; + CAR %from; HASH_KEY @from_hash; DUP; DIP{ DIP { SWAP }; SWAP}; GET; + # Account does not exist + IF_NONE { PUSH string "Account does not exist"; PAIR; FAILWITH } + # Account exists + { RENAME @previous_balance; + DIP { DROP }; + DUP; DIIP{ DUP; CDAR %withdraw_amount; DUP }; + # Ensure funds are available + DIP{ CMPLT @not_enough }; SWAP; + IF { PUSH string "Not enough funds"; FAILWITH } + { SUB @new_balance; DIP{ DUP; DIP{ SWAP }}; DUP; + # Delete account if balance is 0 + PUSH @zero mutez 0; CMPEQ @null_balance; + IF { DROP; NONE @new_balance mutez } + # Otherwise update storage with new balance + { SOME @new_balance }; + SWAP; CAR %from; HASH_KEY @from_hash; UPDATE; + SWAP; DUP; CDAR %withdraw_amount; + # Execute the transfer + DIP{ CAR %from; HASH_KEY @from_hash; IMPLICIT_ACCOUNT @from_account}; UNIT; + TRANSFER_TOKENS @withdraw_transfer_op; + NIL operation; SWAP; CONS; + PAIR }}}} diff --git a/tests_python/contracts_009/attic/add1.tz b/tests_python/contracts_009/attic/add1.tz new file mode 100644 index 0000000000000000000000000000000000000000..78d4f9d1c020bdd05948ff67f69cbb65b057b16c --- /dev/null +++ b/tests_python/contracts_009/attic/add1.tz @@ -0,0 +1,7 @@ +parameter int; +storage int; +code {CAR; # Get the parameter + PUSH int 1; # We're adding 1, so we need to put 1 on the stack + ADD; # Add the two numbers + NIL operation; # We put an empty list of operations on the stack + PAIR} # Create the end value diff --git a/tests_python/contracts_009/attic/add1_list.tz b/tests_python/contracts_009/attic/add1_list.tz new file mode 100644 index 0000000000000000000000000000000000000000..c11616286475571c866d9454bab1cf42614fff4f --- /dev/null +++ b/tests_python/contracts_009/attic/add1_list.tz @@ -0,0 +1,6 @@ +parameter (list int); +storage (list int); +code { CAR; # Get the parameter + MAP { PUSH int 1; ADD }; # Map over the list adding one + NIL operation; # No internal op + PAIR } # Match the calling convention diff --git a/tests_python/contracts_009/attic/after_strategy.tz b/tests_python/contracts_009/attic/after_strategy.tz new file mode 100644 index 0000000000000000000000000000000000000000..70812e52b2001bd349888e7e2330e898e7573007 --- /dev/null +++ b/tests_python/contracts_009/attic/after_strategy.tz @@ -0,0 +1,3 @@ +parameter nat; +storage (pair (pair nat bool) timestamp); +code {DUP; CAR; DIP{CDDR; DUP; NOW; CMPGT}; PAIR; PAIR ; NIL operation ; PAIR}; diff --git a/tests_python/contracts_009/attic/always.tz b/tests_python/contracts_009/attic/always.tz new file mode 100644 index 0000000000000000000000000000000000000000..a7802fec96c84d23efbb859ebff841fef98a5b06 --- /dev/null +++ b/tests_python/contracts_009/attic/always.tz @@ -0,0 +1,4 @@ +parameter nat; +storage (pair nat bool); +code { CAR; PUSH bool True; SWAP; + PAIR; NIL operation; PAIR} diff --git a/tests_python/contracts_009/attic/append.tz b/tests_python/contracts_009/attic/append.tz new file mode 100644 index 0000000000000000000000000000000000000000..3b8335455dcddf866df1515b32ea367a56fccf31 --- /dev/null +++ b/tests_python/contracts_009/attic/append.tz @@ -0,0 +1,8 @@ +parameter (pair (list int) (list int)); +storage (list int); +code { CAR; UNPAIR ; # Unpack lists + NIL int; SWAP; # Setup reverse accumulator + ITER {CONS}; # Reverse list + ITER {CONS}; # Append reversed list + NIL operation; + PAIR} diff --git a/tests_python/contracts_009/attic/at_least.tz b/tests_python/contracts_009/attic/at_least.tz new file mode 100644 index 0000000000000000000000000000000000000000..6c6d2968cd12b8648e663fce9329bac78bc3fe94 --- /dev/null +++ b/tests_python/contracts_009/attic/at_least.tz @@ -0,0 +1,6 @@ +parameter unit; +storage mutez; # How much you have to send me +code {CDR; DUP; # Get the amount required (once for comparison, once to save back in storage) + AMOUNT; CMPLT; # Check to make sure no one is wasting my time + IF {FAIL} # Reject the person + {NIL operation;PAIR}} # Finish the transaction diff --git a/tests_python/contracts_009/attic/auction.tz b/tests_python/contracts_009/attic/auction.tz new file mode 100644 index 0000000000000000000000000000000000000000..af8aedfb7c2287916aed04328244ed89cc4d79d4 --- /dev/null +++ b/tests_python/contracts_009/attic/auction.tz @@ -0,0 +1,8 @@ +parameter key_hash; +storage (pair timestamp (pair mutez key_hash)); +code { DUP; CDAR; DUP; NOW; CMPGT; IF {FAIL} {}; SWAP; # Check if auction has ended + DUP; CAR; DIP{CDDR}; AMOUNT; PAIR; SWAP; DIP{SWAP; PAIR}; # Setup replacement storage + DUP; CAR; AMOUNT; CMPLE; IF {FAIL} {}; # Check to make sure that the new amount is greater + DUP; CAR; # Get amount of refund + DIP{CDR; IMPLICIT_ACCOUNT}; UNIT; TRANSFER_TOKENS; # Make refund + NIL operation; SWAP; CONS; PAIR} # Calling convention diff --git a/tests_python/contracts_009/attic/bad_lockup.tz b/tests_python/contracts_009/attic/bad_lockup.tz new file mode 100644 index 0000000000000000000000000000000000000000..f334e899e71cfe2d8cda8bcc2ef3295384fddb78 --- /dev/null +++ b/tests_python/contracts_009/attic/bad_lockup.tz @@ -0,0 +1,6 @@ +parameter unit; +storage (pair timestamp (pair address address)); +code { CDR; DUP; CAR; NOW; CMPLT; IF {FAIL} {}; + DUP; CDAR; CONTRACT unit ; ASSERT_SOME ; PUSH mutez 100000000; UNIT; TRANSFER_TOKENS; SWAP; + DUP; CDDR; CONTRACT unit ; ASSERT_SOME ; PUSH mutez 100000000; UNIT; TRANSFER_TOKENS; DIP {SWAP} ; + NIL operation ; SWAP ; CONS ; SWAP ; CONS ; PAIR } diff --git a/tests_python/contracts_009/attic/big_map_union.tz b/tests_python/contracts_009/attic/big_map_union.tz new file mode 100644 index 0000000000000000000000000000000000000000..0c971ff11ce9c9fdcd464b3446afdeb06671471f --- /dev/null +++ b/tests_python/contracts_009/attic/big_map_union.tz @@ -0,0 +1,8 @@ +parameter (list (pair string int)) ; +storage (pair (big_map string int) unit) ; +code { UNPAPAIR ; + ITER { UNPAIR ; DUUUP ; DUUP; GET ; + IF_NONE { PUSH int 0 } {} ; + SWAP ; DIP { ADD ; SOME } ; + UPDATE } ; + PAIR ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/attic/cadr_annotation.tz b/tests_python/contracts_009/attic/cadr_annotation.tz new file mode 100644 index 0000000000000000000000000000000000000000..3f4978aebf9e262c576a23b073c99da37c2c41a5 --- /dev/null +++ b/tests_python/contracts_009/attic/cadr_annotation.tz @@ -0,0 +1,3 @@ +parameter (pair (pair %p1 unit (string %no_name)) bool); +storage unit; +code { CAR @param; CADR @name %no_name; DROP; UNIT; NIL operation; PAIR } diff --git a/tests_python/contracts_009/attic/concat.tz b/tests_python/contracts_009/attic/concat.tz new file mode 100644 index 0000000000000000000000000000000000000000..26814afca55add79c28f838472e1ca148599503b --- /dev/null +++ b/tests_python/contracts_009/attic/concat.tz @@ -0,0 +1,7 @@ +parameter string; +storage string; +code { DUP; + DIP { CDR ; NIL string ; SWAP ; CONS } ; + CAR ; CONS ; + CONCAT; + NIL operation; PAIR} diff --git a/tests_python/contracts_009/attic/conditionals.tz b/tests_python/contracts_009/attic/conditionals.tz new file mode 100644 index 0000000000000000000000000000000000000000..16bf8e91645cd8568db65524744b4d185dfa5559 --- /dev/null +++ b/tests_python/contracts_009/attic/conditionals.tz @@ -0,0 +1,9 @@ +parameter (or string (option int)); +storage string; +code { CAR; # Access the storage + IF_LEFT {} # The string is on top of the stack, nothing to do + { IF_NONE { FAIL} # Fail if None + { PUSH int 0; CMPGT; # Check for negative number + IF {FAIL} # Fail if negative + {PUSH string ""}}}; # Push the empty string + NIL operation; PAIR} # Calling convention diff --git a/tests_python/contracts_009/attic/cons_twice.tz b/tests_python/contracts_009/attic/cons_twice.tz new file mode 100644 index 0000000000000000000000000000000000000000..4761b23f71f11a81cca41b0c2f0586163ea3bae7 --- /dev/null +++ b/tests_python/contracts_009/attic/cons_twice.tz @@ -0,0 +1,9 @@ +parameter nat; +storage (list nat); +code { DUP; # Duplicate the storage and parameter + CAR; # Extract the parameter + DIP{CDR}; # Extract the storage + DUP; # Duplicate the parameter + DIP{CONS}; # Add the first instance of the parameter to the list + CONS; # Add the second instance of the parameter to the list + NIL operation; PAIR} # Finish the calling convention diff --git a/tests_python/contracts_009/attic/cps_fact.tz b/tests_python/contracts_009/attic/cps_fact.tz new file mode 100644 index 0000000000000000000000000000000000000000..6c8ee71462904c1d9e2c91fedec8273ec75d0d89 --- /dev/null +++ b/tests_python/contracts_009/attic/cps_fact.tz @@ -0,0 +1,16 @@ +storage nat ; +parameter nat ; +code { UNPAIR ; + DIP { SELF ; ADDRESS ; SENDER; + IFCMPEQ {} { DROP ; PUSH @storage nat 1 } }; + DUP ; + PUSH nat 1 ; + IFCMPGE + { DROP ; NIL operation ; PAIR } + { PUSH nat 1 ; SWAP ; SUB @parameter ; ISNAT ; + IF_NONE + { NIL operation ; PAIR } + { DUP ; DIP { PUSH nat 1 ; ADD ; MUL @storage } ; SWAP; + DIP { DIP { SELF; PUSH mutez 0 } ; + TRANSFER_TOKENS ; NIL operation ; SWAP ; CONS } ; + SWAP ; PAIR } } } \ No newline at end of file diff --git a/tests_python/contracts_009/attic/create_add1_lists.tz b/tests_python/contracts_009/attic/create_add1_lists.tz new file mode 100644 index 0000000000000000000000000000000000000000..5a4245966379e4ae96d793947dbec877ab9165a3 --- /dev/null +++ b/tests_python/contracts_009/attic/create_add1_lists.tz @@ -0,0 +1,14 @@ +parameter unit; +storage address; +code { DROP; NIL int; # starting storage for contract + AMOUNT; # Push the starting balance + NONE key_hash; # No delegate + CREATE_CONTRACT # Create the contract + { parameter (list int) ; + storage (list int) ; + code + { CAR; + MAP {PUSH int 1; ADD}; + NIL operation; + PAIR } }; + NIL operation; SWAP; CONS; PAIR} # Ending calling convention stuff diff --git a/tests_python/contracts_009/attic/data_publisher.tz b/tests_python/contracts_009/attic/data_publisher.tz new file mode 100644 index 0000000000000000000000000000000000000000..9240d63021bc7679b652ee3237adf0f1874d4063 --- /dev/null +++ b/tests_python/contracts_009/attic/data_publisher.tz @@ -0,0 +1,8 @@ +parameter (pair signature (pair string nat)); +storage (pair (pair key nat) string); +code { DUP; CAR; DIP{CDR; DUP}; + SWAP; DIP{DUP}; CAAR; DIP{DUP; CAR; DIP{CDR; PACK ; BLAKE2B}}; + CHECK_SIGNATURE; + IF { CDR; DUP; DIP{CAR; DIP{CAAR}}; CDR; PUSH nat 1; ADD; + DIP{SWAP}; SWAP; PAIR; PAIR; NIL operation; PAIR} + {FAIL}} diff --git a/tests_python/contracts_009/attic/dispatch.tz b/tests_python/contracts_009/attic/dispatch.tz new file mode 100644 index 0000000000000000000000000000000000000000..9c185133ac7fdc3bdf9d87ff79b09096d21ecb19 --- /dev/null +++ b/tests_python/contracts_009/attic/dispatch.tz @@ -0,0 +1,9 @@ +parameter (or string (pair string (lambda unit string))); +storage (pair string (map string (lambda unit string))); +code { DUP; DIP{CDDR}; CAR; # Unpack stack + IF_LEFT { DIP{DUP}; GET; # Get lambda if it exists + IF_NONE {FAIL} {}; # Fail if it doesn't + UNIT; EXEC } # Execute the lambda + { DUP; CAR; DIP {CDR; SOME}; UPDATE; PUSH string ""}; # Update the storage + PAIR; + NIL operation; PAIR} # Calling convention diff --git a/tests_python/contracts_009/attic/empty.tz b/tests_python/contracts_009/attic/empty.tz new file mode 100644 index 0000000000000000000000000000000000000000..d3aecdb250663942028ede3532a878c090a8b613 --- /dev/null +++ b/tests_python/contracts_009/attic/empty.tz @@ -0,0 +1,3 @@ +parameter unit; +storage unit; +code {CDR; NIL operation; PAIR} diff --git a/tests_python/contracts_009/attic/fail_amount.tz b/tests_python/contracts_009/attic/fail_amount.tz new file mode 100644 index 0000000000000000000000000000000000000000..95b71c4f0ff120c019650f250ccb8f6d620b186b --- /dev/null +++ b/tests_python/contracts_009/attic/fail_amount.tz @@ -0,0 +1,6 @@ +# Fail if the amount transferred is less than 10 +parameter unit; +storage unit; +code { DROP; + AMOUNT; PUSH mutez 10000000; CMPGT; IF {FAIL} {}; + UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/attic/faucet.tz b/tests_python/contracts_009/attic/faucet.tz new file mode 100644 index 0000000000000000000000000000000000000000..0c92a0744d9452ab97c5c79401f89819577feaf0 --- /dev/null +++ b/tests_python/contracts_009/attic/faucet.tz @@ -0,0 +1,7 @@ +parameter key_hash ; +storage timestamp ; +code { UNPAIR ; SWAP ; + PUSH int 300 ; ADD @FIVE_MINUTES_LATER ; + NOW ; ASSERT_CMPGE ; + IMPLICIT_ACCOUNT ; PUSH mutez 1000000 ; UNIT ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; DIP { NOW } ; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/attic/forward.tz b/tests_python/contracts_009/attic/forward.tz new file mode 100644 index 0000000000000000000000000000000000000000..5b66891bb1bf58a42202f88b08903a81044a9bff --- /dev/null +++ b/tests_python/contracts_009/attic/forward.tz @@ -0,0 +1,150 @@ +parameter + (or string nat) ; +storage + (pair + (pair nat (pair mutez mutez)) # counter from_buyer from_seller + (pair + (pair nat (pair timestamp timestamp)) # Q T Z + (pair + (pair mutez mutez) # K C + (pair + (pair address address) # B S + address)))) ; # W +code + { DUP ; CDDADDR ; # Z + PUSH int 86400 ; SWAP ; ADD ; # one day in second + NOW ; COMPARE ; LT ; + IF { # Before Z + 24 + DUP ; CAR ; # we must receive (Left "buyer") or (Left "seller") + IF_LEFT + { DUP ; PUSH string "buyer" ; COMPARE ; EQ ; + IF { DROP ; + DUP ; CDADAR ; # amount already versed by the buyer + DIP { AMOUNT } ; ADD ; # transaction + # then we rebuild the globals + DIP { DUP ; CDADDR } ; PAIR ; # seller amount + PUSH nat 0 ; PAIR ; # delivery counter at 0 + DIP { CDDR } ; PAIR ; # parameters + # and return Unit + NIL operation ; PAIR } + { PUSH string "seller" ; COMPARE ; EQ ; + IF { DUP ; CDADDR ; # amount already versed by the seller + DIP { AMOUNT } ; ADD ; # transaction + # then we rebuild the globals + DIP { DUP ; CDADAR } ; SWAP ; PAIR ; # buyer amount + PUSH nat 0 ; PAIR ; # delivery counter at 0 + DIP { CDDR } ; PAIR ; # parameters + # and return Unit + NIL operation ; PAIR } + { FAIL } } } # (Left _) + { FAIL } } # (Right _) + { # After Z + 24 + # if balance is emptied, just fail + BALANCE ; PUSH mutez 0 ; IFCMPEQ { FAIL } {} ; + # test if the required amount is reached + DUP ; CDDAAR ; # Q + DIP { DUP ; CDDDADR } ; MUL ; # C + PUSH nat 2 ; MUL ; + BALANCE ; COMPARE ; LT ; # balance < 2 * (Q * C) + IF { # refund the parties + CDR ; DUP ; CADAR ; # amount versed by the buyer + DIP { DUP ; CDDDAAR } ; # B + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; SWAP ; + DUP ; CADDR ; # amount versed by the seller + DIP { DUP ; CDDDADR } ; # S + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS ; SWAP ; + DIP { CONS } ; + DUP ; CADAR ; DIP { DUP ; CADDR } ; ADD ; + BALANCE ; SUB ; # bonus to the warehouse + DIP { DUP ; CDDDDR } ; # W + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS ; + DIP { SWAP } ; CONS ; + # leave the storage as-is, as the balance is now 0 + PAIR } + { # otherwise continue + DUP ; CDDADAR ; # T + NOW ; COMPARE ; LT ; + IF { FAIL } # Between Z + 24 and T + { # after T + DUP ; CDDADAR ; # T + PUSH int 86400 ; ADD ; # one day in second + NOW ; COMPARE ; LT ; + IF { # Between T and T + 24 + # we only accept transactions from the buyer + DUP ; CAR ; # we must receive (Left "buyer") + IF_LEFT + { PUSH string "buyer" ; COMPARE ; EQ ; + IF { DUP ; CDADAR ; # amount already versed by the buyer + DIP { AMOUNT } ; ADD ; # transaction + # The amount must not exceed Q * K + DUP ; + DIIP { DUP ; CDDAAR ; # Q + DIP { DUP ; CDDDAAR } ; MUL ; } ; # K + DIP { COMPARE ; GT ; # new amount > Q * K + IF { FAIL } { } } ; # abort or continue + # then we rebuild the globals + DIP { DUP ; CDADDR } ; PAIR ; # seller amount + PUSH nat 0 ; PAIR ; # delivery counter at 0 + DIP { CDDR } ; PAIR ; # parameters + # and return Unit + NIL operation ; PAIR } + { FAIL } } # (Left _) + { FAIL } } # (Right _) + { # After T + 24 + # test if the required payment is reached + DUP ; CDDAAR ; # Q + DIP { DUP ; CDDDAAR } ; MUL ; # K + DIP { DUP ; CDADAR } ; # amount already versed by the buyer + COMPARE ; NEQ ; + IF { # not reached, pay the seller + BALANCE ; + DIP { DUP ; CDDDDADR } ; # S + DIIP { CDR } ; + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; PAIR } + { # otherwise continue + DUP ; CDDADAR ; # T + PUSH int 86400 ; ADD ; + PUSH int 86400 ; ADD ; # two days in second + NOW ; COMPARE ; LT ; + IF { # Between T + 24 and T + 48 + # We accept only delivery notifications, from W + DUP ; CDDDDDR ; # W + SENDER ; + COMPARE ; NEQ ; + IF { FAIL } {} ; # fail if not the warehouse + DUP ; CAR ; # we must receive (Right amount) + IF_LEFT + { FAIL } # (Left _) + { # We increment the counter + DIP { DUP ; CDAAR } ; ADD ; + # And rebuild the globals in advance + DIP { DUP ; CDADR } ; PAIR ; + DIP { CDDR } ; PAIR ; + UNIT ; PAIR ; + # We test if enough have been delivered + DUP ; CDAAR ; + DIP { DUP ; CDDAAR } ; + COMPARE ; LT ; # counter < Q + IF { CDR ; NIL operation } # wait for more + { # Transfer all the money to the seller + BALANCE ; + DIP { DUP ; CDDDDADR } ; # S + DIIP { CDR } ; + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS } } ; + PAIR } + { # after T + 48, transfer everything to the buyer + BALANCE ; + DIP { DUP ; CDDDDAAR } ; # B + DIIP { CDR } ; + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; + PAIR} } } } } } } \ No newline at end of file diff --git a/tests_python/contracts_009/attic/id.tz b/tests_python/contracts_009/attic/id.tz new file mode 100644 index 0000000000000000000000000000000000000000..4eee565ca2e957d2b7f225eae5481edee6a24932 --- /dev/null +++ b/tests_python/contracts_009/attic/id.tz @@ -0,0 +1,3 @@ +parameter string; +storage string; +code {CAR; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/attic/infinite_loop.tz b/tests_python/contracts_009/attic/infinite_loop.tz new file mode 100644 index 0000000000000000000000000000000000000000..77cdbc48c0d1d26e6f38a80cfe4a55b9ac6357e8 --- /dev/null +++ b/tests_python/contracts_009/attic/infinite_loop.tz @@ -0,0 +1,3 @@ +parameter unit; +storage unit; +code { DROP; PUSH bool True; LOOP {PUSH bool True}; UNIT; NIL operation; PAIR } diff --git a/tests_python/contracts_009/attic/insertion_sort.tz b/tests_python/contracts_009/attic/insertion_sort.tz new file mode 100644 index 0000000000000000000000000000000000000000..34eca64d092cbae52a88508d8d2a1664bc2caca6 --- /dev/null +++ b/tests_python/contracts_009/attic/insertion_sort.tz @@ -0,0 +1,16 @@ +parameter (list int) ; +storage (list int) ; +code { CAR ; + NIL int ; SWAP ; + ITER { SWAP; DIIP{NIL int} ; PUSH bool True ; + LOOP + { IF_CONS + { SWAP ; + DIP{DUP ; DIIP{DUP} ; DIP{CMPLT} ; SWAP} ; + SWAP ; + IF { DIP{SWAP ; DIP{CONS}} ; PUSH bool True} + { SWAP ; CONS ; PUSH bool False}} + { NIL int ; PUSH bool False}} ; + SWAP ; CONS ; SWAP ; + ITER {CONS}} ; + NIL operation ; PAIR } diff --git a/tests_python/contracts_009/attic/int_publisher.tz b/tests_python/contracts_009/attic/int_publisher.tz new file mode 100644 index 0000000000000000000000000000000000000000..6ee49b979e2c0185a53832a574c691cfd1e810d3 --- /dev/null +++ b/tests_python/contracts_009/attic/int_publisher.tz @@ -0,0 +1,17 @@ +# (signed hash of the string, string) +parameter (option (pair signature int)); +storage (pair key int); +code {DUP; DUP; CAR; + IF_NONE {PUSH mutez 1000000; # Fee pattern from July 26 + AMOUNT; CMPLE; IF {FAIL} {}; + # Provide the data + CDR; DIP {CDDR}} + {DUP; DIP{SWAP}; SWAP; CDAR; # Move key to the top + DIP {DUP; CAR; DIP {CDR; PACK ; BLAKE2B}}; # Arrange the new piece of data + CHECK_SIGNATURE; # Check to ensure the data is authentic + # Update data + IF {CDR; SWAP; DIP{DUP}; CDAR; PAIR} + # Revert the update. This could be replaced with FAIL + {DROP; DUP; CDR; DIP{CDDR}}}; + # Cleanup + DIP{DROP}; NIL operation; PAIR} diff --git a/tests_python/contracts_009/attic/king_of_tez.tz b/tests_python/contracts_009/attic/king_of_tez.tz new file mode 100644 index 0000000000000000000000000000000000000000..033ead7f168c95c41e59bbaad2a35e73c75b324a --- /dev/null +++ b/tests_python/contracts_009/attic/king_of_tez.tz @@ -0,0 +1,19 @@ +parameter key_hash; +storage (pair timestamp (pair mutez key_hash)); +code { DUP; CDAR; + # If the time is more than 2 weeks, any amount makes you king + NOW; CMPGT; + # User becomes king of mutez + IF { CAR; AMOUNT; PAIR; NOW; PUSH int 604800; ADD; PAIR; + NIL operation } + # Check balance to see if user has paid enough to become the new king + { DUP; CDDAR; AMOUNT; CMPLT; + IF { FAIL } # user has not paid out + { CAR; DUP; + # New storage + DIP{ AMOUNT; PAIR; NOW; PUSH int 604800; ADD; PAIR }; + # Pay funds to old king + IMPLICIT_ACCOUNT; AMOUNT; UNIT; TRANSFER_TOKENS; + NIL operation; SWAP; CONS}}; + # Cleanup + PAIR }; diff --git a/tests_python/contracts_009/attic/list_of_transactions.tz b/tests_python/contracts_009/attic/list_of_transactions.tz new file mode 100644 index 0000000000000000000000000000000000000000..620ceedd5a678613b004e6744347bbfe309b456e --- /dev/null +++ b/tests_python/contracts_009/attic/list_of_transactions.tz @@ -0,0 +1,8 @@ +parameter unit; +storage (list address); +code { CDR; DUP; + DIP {NIL operation}; PUSH bool True; # Setup loop + LOOP {IF_CONS { CONTRACT unit ; ASSERT_SOME ; PUSH mutez 1000000; UNIT; TRANSFER_TOKENS; # Make transfer + SWAP; DIP {CONS}; PUSH bool True} # Setup for next round of loop + { NIL address ; PUSH bool False}}; # Data to satisfy types and end loop + DROP; PAIR}; # Calling convention diff --git a/tests_python/contracts_009/attic/queue.tz b/tests_python/contracts_009/attic/queue.tz new file mode 100644 index 0000000000000000000000000000000000000000..a074906ddf9182544945d49d5f0920d382e34f58 --- /dev/null +++ b/tests_python/contracts_009/attic/queue.tz @@ -0,0 +1,24 @@ +parameter (option string); +storage (pair (option string) (pair (pair nat nat) (map nat string))); +code { DUP; CAR; + # Retrieving an element + IF_NONE { CDDR; DUP; CAR; DIP{CDR; DUP}; DUP; + CAR; SWAP; DIP{GET}; # Check if an element is available + SWAP; + # Put NONE on stack and finish + IF_NONE { NONE string; DIP{PAIR}; PAIR} + # Reoption the element and remove the entry from the map + { SOME; + DIP{ DUP; DIP{ CAR; DIP{ NONE string }; UPDATE }; + # Increment the counter and cleanup + DUP; CAR; PUSH nat 1; ADD; DIP{ CDR }; PAIR; PAIR}; + PAIR }} + # Arrange the stack + { DIP{DUP; CDDAR; DIP{CDDDR}; DUP}; SWAP; CAR; + # Add the element to the map + DIP{ SOME; SWAP; CDR; DUP; DIP{UPDATE}; + # Increment the second number + PUSH nat 1; ADD}; + # Cleanup and finish + PAIR; PAIR; NONE string; PAIR }; + NIL operation; PAIR} diff --git a/tests_python/contracts_009/attic/reduce_map.tz b/tests_python/contracts_009/attic/reduce_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..aab8ea60d367658a1be2c664414f528ae522ad69 --- /dev/null +++ b/tests_python/contracts_009/attic/reduce_map.tz @@ -0,0 +1,16 @@ + +parameter (pair (lambda int int) (list int)); +storage (list int); +code { DIP{NIL int}; + CAR; + DUP; + DIP{CAR; PAIR}; # Unpack data and setup accumulator + CDR; + ITER {PAIR; + DUP; CDAR; + DIP{ DUP; DIP{CDAR}; DUP; + CAR; DIP{CDDR; SWAP}; EXEC; CONS}; + PAIR}; + CDR; DIP{NIL int}; # First reduce + ITER {CONS}; # Reverse + NIL operation; PAIR} # Calling convention diff --git a/tests_python/contracts_009/attic/reentrancy.tz b/tests_python/contracts_009/attic/reentrancy.tz new file mode 100644 index 0000000000000000000000000000000000000000..b9e614a4e53e9b0772872e81a43900b5363a2a34 --- /dev/null +++ b/tests_python/contracts_009/attic/reentrancy.tz @@ -0,0 +1,7 @@ +parameter unit; +storage (pair address address); +code { CDR; DUP; CAR; + CONTRACT unit ; ASSERT_SOME ; PUSH mutez 5000000; UNIT; TRANSFER_TOKENS; + DIP {DUP; CDR; + CONTRACT unit ; ASSERT_SOME ; PUSH mutez 5000000; UNIT; TRANSFER_TOKENS}; + DIIP{NIL operation};DIP{CONS};CONS;PAIR}; diff --git a/tests_python/contracts_009/attic/reservoir.tz b/tests_python/contracts_009/attic/reservoir.tz new file mode 100644 index 0000000000000000000000000000000000000000..291e09b262b58110d971fa23ca8badcc1f93164f --- /dev/null +++ b/tests_python/contracts_009/attic/reservoir.tz @@ -0,0 +1,25 @@ +parameter unit ; +storage + (pair + (pair (timestamp %T) (mutez %N)) + (pair (address %A) (address %B))) ; +code + { CDR ; DUP ; CAAR %T; # T + NOW ; COMPARE ; LE ; + IF { DUP ; CADR %N; # N + BALANCE ; + COMPARE ; LE ; + IF { NIL operation ; PAIR } + { DUP ; CDDR %B; # B + CONTRACT unit ; ASSERT_SOME ; + BALANCE ; UNIT ; + TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; + PAIR } } + { DUP ; CDAR %A; # A + CONTRACT unit ; ASSERT_SOME ; + BALANCE ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; + PAIR } } diff --git a/tests_python/contracts_009/attic/scrutable_reservoir.tz b/tests_python/contracts_009/attic/scrutable_reservoir.tz new file mode 100644 index 0000000000000000000000000000000000000000..d415cdda0f54950d0210a1323d157ca9d61f84fc --- /dev/null +++ b/tests_python/contracts_009/attic/scrutable_reservoir.tz @@ -0,0 +1,67 @@ +parameter unit ; +storage + (pair + string # S + (pair + timestamp # T + (pair + (pair mutez mutez) # P N + (pair + address # X + (pair address address))))) ; # A B +code + { DUP ; CDAR ; # S + PUSH string "open" ; + COMPARE ; NEQ ; + IF { FAIL } # on "success", "timeout" or a bad init value + { DUP ; CDDAR ; # T + NOW ; + COMPARE ; LT ; + IF { # Before timeout + # We compute (P + N) mutez + PUSH mutez 0 ; + DIP { DUP ; CDDDAAR } ; ADD ; # P + DIP { DUP ; CDDDADR } ; ADD ; # N + # We compare to the cumulated amount + BALANCE ; + COMPARE; LT ; + IF { # Not enough cash, we just accept the transaction + # and leave the global untouched + CDR ; NIL operation ; PAIR } + { # Enough cash, successful ending + # We update the global + CDDR ; PUSH string "success" ; PAIR ; + # We transfer the fee to the broker + DUP ; CDDAAR ; # P + DIP { DUP ; CDDDAR } ; # X + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS ; + # We transfer the rest to A + DIP { DUP ; CDDADR ; # N + DIP { DUP ; CDDDDAR } ; # A + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS } ; + NIL operation ; SWAP ; CONS ; SWAP ; CONS ; + PAIR } } + { # After timeout, we refund + # We update the global + CDDR ; PUSH string "timeout" ; PAIR ; + # We try to transfer the fee to the broker + BALANCE ; # available + DIP { DUP ; CDDAAR } ; # P + COMPARE ; LT ; # available < P + IF { BALANCE ; # available + DIP { DUP ; CDDDAR } ; # X + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS } + { DUP ; CDDAAR ; # P + DIP { DUP ; CDDDAR } ; # X + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS } ; + # We transfer the rest to B + DIP { BALANCE ; # available + DIP { DUP ; CDDDDDR } ; # B + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT ; TRANSFER_TOKENS } ; + NIL operation ; SWAP ; CONS ; SWAP ; CONS ; + PAIR } } } diff --git a/tests_python/contracts_009/attic/spawn_identities.tz b/tests_python/contracts_009/attic/spawn_identities.tz new file mode 100644 index 0000000000000000000000000000000000000000..2208e0d0928d2872d44e5b9b0a47dcfdc7a71bba --- /dev/null +++ b/tests_python/contracts_009/attic/spawn_identities.tz @@ -0,0 +1,20 @@ +parameter nat; +storage (list address); +code { DUP; + CAR; # Get the number + DIP{CDR; NIL operation}; # Put the accumulators on the stack + PUSH bool True; # Push true so we have a do while loop + LOOP { DUP; PUSH nat 0; CMPEQ; # Check if the number is 0 + IF { PUSH bool False} # End the loop + { PUSH nat 1; SWAP; SUB; ABS; # Subtract 1. The ABS is to make it back into a nat + PUSH string "init"; # Storage type + PUSH mutez 5000000; # Starting balance + NONE key_hash; + CREATE_CONTRACT + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } ; # Make the contract + SWAP ; DIP { SWAP ; DIP { CONS } } ; # emit the operation + SWAP ; DIP { SWAP ; DIP { CONS } } ; # add to the list + PUSH bool True}}; # Continue the loop + DROP; PAIR} # Calling convention diff --git a/tests_python/contracts_009/entrypoints/big_map_entrypoints.tz b/tests_python/contracts_009/entrypoints/big_map_entrypoints.tz new file mode 100644 index 0000000000000000000000000000000000000000..d49e6257167affbe689e6b4654ccfdf4cc828240 --- /dev/null +++ b/tests_python/contracts_009/entrypoints/big_map_entrypoints.tz @@ -0,0 +1,31 @@ +storage + (pair (big_map string nat) (big_map string nat)) ; +parameter + (or (unit %default) + (or (or %mem (string %mem_left) (string %mem_right)) + (or (or %add (pair %add_left string nat) (pair %add_right string nat)) + (or %rem (string %rem_left) (string %rem_right))))) ; +code { UNPAIR ; + IF_LEFT + { DROP ; + DUP ; CAR ; + PUSH mutez 0 ; + NONE key_hash ; + CREATE_CONTRACT + { parameter string ; + storage (big_map string nat) ; + code { UNPAIR ; DROP ; NIL operation ; PAIR }} ; + DIP { DROP } ; + NIL operation ; SWAP ; CONS ; PAIR } + { IF_LEFT + { IF_LEFT + { DIP { UNPAIR } ; DIP { DUP } ; MEM ; ASSERT } + { DIP { UNPAIR ; SWAP } ; DIP { DUP } ; MEM ; ASSERT ; SWAP } } + { IF_LEFT + { IF_LEFT + { UNPAIR ; DIIP { UNPAIR } ; DIP { SOME } ; UPDATE } + { UNPAIR ; DIIP { UNPAIR ; SWAP } ; DIP { SOME } ; UPDATE ; SWAP } } + { IF_LEFT + { DIP { UNPAIR } ; DIP { NONE nat } ; UPDATE } + { DIP { UNPAIR ; SWAP } ; DIP { NONE nat } ; UPDATE ; SWAP } } } ; + PAIR ; NIL operation ; PAIR } } diff --git a/tests_python/contracts_009/entrypoints/delegatable_target.tz b/tests_python/contracts_009/entrypoints/delegatable_target.tz new file mode 100644 index 0000000000000000000000000000000000000000..0db00f4945ed0fa3ea1c4f71607dfa45cdbe0319 --- /dev/null +++ b/tests_python/contracts_009/entrypoints/delegatable_target.tz @@ -0,0 +1,79 @@ +# Michelson pseudo-code to transform from source script. + # This transformation adds 'set_delegate' entrypoint, e.g.: + # + # parameter ; + # storage ; + # code ; + # + # to: +parameter + (or + (or (key_hash %set_delegate) + (unit %remove_delegate)) + (or %default string nat) + ) ; + +storage + (pair + key_hash # manager + (pair string nat) + ) ; + +code { + DUP ; + CAR ; + IF_LEFT + { # 'set_delegate'/'remove_delegate' entrypoints + # Assert no token was sent: + # to send tokens, the default entry point should be used + PUSH mutez 0 ; + AMOUNT ; + ASSERT_CMPEQ ; + # Assert that the sender is the manager + DUUP ; + CDR ; + CAR ; + IMPLICIT_ACCOUNT ; ADDRESS ; + SENDER ; + IFCMPNEQ + { SENDER ; + PUSH string "Only the owner can operate." ; + PAIR ; + FAILWITH ; + } + { DIP { CDR ; NIL operation } ; + IF_LEFT + { # 'set_delegate' entrypoint + SOME ; + SET_DELEGATE ; + CONS ; + PAIR ; + } + { # 'remove_delegate' entrypoint + DROP ; + NONE key_hash ; + SET_DELEGATE ; + CONS ; + PAIR ; + } + } + } + { # Transform the inputs to the original script types + DIP { CDR ; DUP ; CDR } ; + PAIR ; + + # 'default' entrypoint - original code + { UNPAIR; + IF_LEFT + { DIP { UNPAIR ; DROP } } + { DUG 1; UNPAIR ; DIP { DROP } } ; + PAIR ; NIL operation ; PAIR } + # Transform the outputs to the new script types (manager's storage is unchanged) + SWAP ; + CAR ; + SWAP ; + UNPAIR ; + DIP { SWAP ; PAIR } ; + PAIR ; + } + } diff --git a/tests_python/contracts_009/entrypoints/manager.tz b/tests_python/contracts_009/entrypoints/manager.tz new file mode 100644 index 0000000000000000000000000000000000000000..06d9b1067bf42117745ed6405bf1dbeeff6c5678 --- /dev/null +++ b/tests_python/contracts_009/entrypoints/manager.tz @@ -0,0 +1,31 @@ +parameter + (or + (lambda %do unit (list operation)) + (unit %default)); +storage key_hash; +code + { UNPAIR ; + IF_LEFT + { # 'do' entrypoint + # Assert no token was sent: + # to send tokens, the default entry point should be used + PUSH mutez 0 ; + AMOUNT ; + ASSERT_CMPEQ ; + # Assert that the sender is the manager + DUUP ; + IMPLICIT_ACCOUNT ; + ADDRESS ; + SENDER ; + ASSERT_CMPEQ ; + # Execute the lambda argument + UNIT ; + EXEC ; + PAIR ; + } + { # 'default' entrypoint + DROP ; + NIL operation ; + PAIR ; + } + }; diff --git a/tests_python/contracts_009/entrypoints/no_default_target.tz b/tests_python/contracts_009/entrypoints/no_default_target.tz new file mode 100644 index 0000000000000000000000000000000000000000..48d5d53df996c53390af50da8aa9193f971192d7 --- /dev/null +++ b/tests_python/contracts_009/entrypoints/no_default_target.tz @@ -0,0 +1,11 @@ +storage (pair string nat) ; +parameter + (or unit (or %data string nat)) ; +code { UNPAIR ; + IF_LEFT + { DROP ; NIL operation ; PAIR } + { IF_LEFT + { DIP { UNPAIR ; DROP } } + { DUG 1; UNPAIR ; DIP { DROP } } ; + PAIR ; NIL operation ; PAIR } + } diff --git a/tests_python/contracts_009/entrypoints/no_entrypoint_target.tz b/tests_python/contracts_009/entrypoints/no_entrypoint_target.tz new file mode 100644 index 0000000000000000000000000000000000000000..d8041507d58cdc79011efa6a1e8d2c7e80c64074 --- /dev/null +++ b/tests_python/contracts_009/entrypoints/no_entrypoint_target.tz @@ -0,0 +1,11 @@ +storage (pair string nat) ; +parameter + (or unit (or string nat)) ; +code { UNPAIR ; + IF_LEFT + { DROP ; NIL operation ; PAIR } + { IF_LEFT + { DIP { UNPAIR ; DROP } } + { DUG 1; UNPAIR ; DIP { DROP } } ; + PAIR ; NIL operation ; PAIR } + } diff --git a/tests_python/contracts_009/entrypoints/rooted_target.tz b/tests_python/contracts_009/entrypoints/rooted_target.tz new file mode 100644 index 0000000000000000000000000000000000000000..2ca2dfb1296d906e87eac5148882b62afce3cd33 --- /dev/null +++ b/tests_python/contracts_009/entrypoints/rooted_target.tz @@ -0,0 +1,11 @@ +storage (pair string nat) ; +parameter + (or %root unit (or %default string nat)) ; +code { UNPAIR ; + IF_LEFT + { DROP ; NIL operation ; PAIR } + { IF_LEFT + { DIP { UNPAIR ; DROP } } + { DUG 1; UNPAIR ; DIP { DROP } } ; + PAIR ; NIL operation ; PAIR } + } diff --git a/tests_python/contracts_009/entrypoints/simple_entrypoints.tz b/tests_python/contracts_009/entrypoints/simple_entrypoints.tz new file mode 100644 index 0000000000000000000000000000000000000000..7b7abb7cb86e2c80059ca5416a63436df2ed44fe --- /dev/null +++ b/tests_python/contracts_009/entrypoints/simple_entrypoints.tz @@ -0,0 +1,4 @@ +# A trivial contract with some entrypoints +parameter (or (unit %A) (or (string %B) (nat %C))) ; +storage unit; +code { CDR ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/ill_typed/big_dip.tz b/tests_python/contracts_009/ill_typed/big_dip.tz new file mode 100644 index 0000000000000000000000000000000000000000..697370fdc87edb483e9614d782b62018d0f3c11f --- /dev/null +++ b/tests_python/contracts_009/ill_typed/big_dip.tz @@ -0,0 +1,4 @@ +parameter unit; +storage unit; +code { DIP 1073741824 { }; # = 0x3fffffff + 1 + DROP; } diff --git a/tests_python/contracts_009/ill_typed/big_drop.tz b/tests_python/contracts_009/ill_typed/big_drop.tz new file mode 100644 index 0000000000000000000000000000000000000000..40d81cf8448bd4fa47c678ec5323964677619d61 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/big_drop.tz @@ -0,0 +1,4 @@ +parameter unit; +storage unit; +code { DROP 1073741824; # = 0x3fffffff + 1 + DROP; } diff --git a/tests_python/contracts_009/ill_typed/big_map_arity.tz b/tests_python/contracts_009/ill_typed/big_map_arity.tz new file mode 100644 index 0000000000000000000000000000000000000000..5e5a7d60d5b75bb33bfcf750761b19ddde5b8756 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/big_map_arity.tz @@ -0,0 +1,5 @@ +# This contract tests the error message in case the EMPTY_BIG_MAP instruction has bad arity (1 argument instead of 2). +# The expected type-checking error is "primitive EMPTY_BIG_MAP expects 2 arguments but is given 1." +parameter unit; +storage unit; +code { DROP; EMPTY_BIG_MAP nat; DROP; UNIT; NIL operation; PAIR; } diff --git a/tests_python/contracts_009/ill_typed/chain_id_arity.tz b/tests_python/contracts_009/ill_typed/chain_id_arity.tz new file mode 100644 index 0000000000000000000000000000000000000000..4bc9f4f70107e6a10d483682f55317fed2bb63f2 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/chain_id_arity.tz @@ -0,0 +1,3 @@ +parameter (chain_id nat); +storage unit; +code { CDR; NIL operation; PAIR } diff --git a/tests_python/contracts_009/ill_typed/comb0.tz b/tests_python/contracts_009/ill_typed/comb0.tz new file mode 100644 index 0000000000000000000000000000000000000000..ab3c79153035ea1a22d36e10f252931d148bec9b --- /dev/null +++ b/tests_python/contracts_009/ill_typed/comb0.tz @@ -0,0 +1,3 @@ +parameter unit; +storage unit; +code { PAIR 0 } diff --git a/tests_python/contracts_009/ill_typed/comb1.tz b/tests_python/contracts_009/ill_typed/comb1.tz new file mode 100644 index 0000000000000000000000000000000000000000..07b709d61cfd61e99759ea91b9cdbc72ad6b5c1f --- /dev/null +++ b/tests_python/contracts_009/ill_typed/comb1.tz @@ -0,0 +1,3 @@ +parameter unit; +storage unit; +code { PAIR 1 } diff --git a/tests_python/contracts_009/ill_typed/contract_annotation_default.tz b/tests_python/contracts_009/ill_typed/contract_annotation_default.tz new file mode 100644 index 0000000000000000000000000000000000000000..742e140c5e480f546735413ee873d3a387e14977 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/contract_annotation_default.tz @@ -0,0 +1,11 @@ +parameter (contract (or (or (int %A) (nat %B)) (unit %default))); +storage unit; +code { + CAR; + # CONTRACT %default nat == CONTRACT nat and the former is not allowed. + DUP; ADDRESS; CONTRACT %default nat; ASSERT_SOME; DROP; + DROP; + UNIT; + NIL operation; + PAIR + }; diff --git a/tests_python/contracts_009/ill_typed/dup0.tz b/tests_python/contracts_009/ill_typed/dup0.tz new file mode 100644 index 0000000000000000000000000000000000000000..2e46599e490a5717ee8dd263bce4c976d06167f5 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/dup0.tz @@ -0,0 +1,3 @@ +parameter unit; +storage unit; +code { DUP 0 } diff --git a/tests_python/contracts_009/ill_typed/failwith_big_map.tz b/tests_python/contracts_009/ill_typed/failwith_big_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..dba12309038cc0b6e74b184b69db38039fd5557c --- /dev/null +++ b/tests_python/contracts_009/ill_typed/failwith_big_map.tz @@ -0,0 +1,22 @@ +# This contract uses FAILWITH to expose a big map diff +# See https://gitlab.com/nomadic-labs/tezos/-/issues/27#note_271401078 + +parameter (big_map int int); + +# Even if the stored big_map is dropped by the initial CAR instruction, +# it can still be accessed by its big-map id and sent as parameter so +# it is important that the type of the storage matches the type of the +# parameter. + +# This test is now ill-typed because FAILWITH accepts only packable types + +storage (big_map int int); + +code { CAR; + PUSH (option int) (Some 1); + PUSH int 1; + UPDATE; + PUSH (option int) None; + PUSH int 2; + UPDATE; + FAILWITH } diff --git a/tests_python/contracts_009/ill_typed/invalid_self_entrypoint.tz b/tests_python/contracts_009/ill_typed/invalid_self_entrypoint.tz new file mode 100644 index 0000000000000000000000000000000000000000..4fac9c63504479d2ef42a60e275af3d495aea371 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/invalid_self_entrypoint.tz @@ -0,0 +1,10 @@ +parameter (or (or (nat %A) (bool %B)) (or %maybe_C (unit %Z) (string %C))); +storage unit; +code { + DROP; + # This entrypoint does not exist + SELF %D; DROP; + UNIT; + NIL operation; + PAIR; + } diff --git a/tests_python/contracts_009/ill_typed/missing_only_code_field.tz b/tests_python/contracts_009/ill_typed/missing_only_code_field.tz new file mode 100644 index 0000000000000000000000000000000000000000..4b5b2cd62f56823e71508cb2a04746d1d6aa7158 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/missing_only_code_field.tz @@ -0,0 +1,2 @@ +storage unit; +parameter nat; \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/missing_only_parameter_field.tz b/tests_python/contracts_009/ill_typed/missing_only_parameter_field.tz new file mode 100644 index 0000000000000000000000000000000000000000..1f7e8ac75da9ef7630c5682f23dc819506fdb886 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/missing_only_parameter_field.tz @@ -0,0 +1,4 @@ +storage unit; +code { CAR; + DUP; NEG; ABS; COMPARE; ASSERT_EQ; + UNIT; NIL operation; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/missing_only_storage_field.tz b/tests_python/contracts_009/ill_typed/missing_only_storage_field.tz new file mode 100644 index 0000000000000000000000000000000000000000..2aa28922287ac88f1e8b94c53a3fb3e8c0e03089 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/missing_only_storage_field.tz @@ -0,0 +1,4 @@ +parameter nat; +code { CAR; + DUP; NEG; ABS; COMPARE; ASSERT_EQ; + UNIT; NIL operation; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/missing_parameter_and_storage_fields.tz b/tests_python/contracts_009/ill_typed/missing_parameter_and_storage_fields.tz new file mode 100644 index 0000000000000000000000000000000000000000..18e7b35b0a8c66be107f53e0e300a6e6b21a371f --- /dev/null +++ b/tests_python/contracts_009/ill_typed/missing_parameter_and_storage_fields.tz @@ -0,0 +1,3 @@ +code { CAR; + DUP; NEG; ABS; COMPARE; ASSERT_EQ; + UNIT; NIL operation; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/multiple_code_field.tz b/tests_python/contracts_009/ill_typed/multiple_code_field.tz new file mode 100644 index 0000000000000000000000000000000000000000..cd47b356d14e60571c7fea85ec80be2db2aa2928 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/multiple_code_field.tz @@ -0,0 +1,6 @@ +parameter nat; +storage unit; +code { CAR; + DUP; NEG; ABS; COMPARE; ASSERT_EQ; + UNIT; NIL operation; PAIR }; +code {} \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/multiple_parameter_field.tz b/tests_python/contracts_009/ill_typed/multiple_parameter_field.tz new file mode 100644 index 0000000000000000000000000000000000000000..e59fb9fe05be6b944e1abd43438aa8600c3466e7 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/multiple_parameter_field.tz @@ -0,0 +1,6 @@ +parameter nat; +parameter nat; +storage unit; +code { CAR; + DUP; NEG; ABS; COMPARE; ASSERT_EQ; + UNIT; NIL operation; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/multiple_storage_and_code_fields.tz b/tests_python/contracts_009/ill_typed/multiple_storage_and_code_fields.tz new file mode 100644 index 0000000000000000000000000000000000000000..3b32484dc200f8300ce10ea2f4d796e27543eb2a --- /dev/null +++ b/tests_python/contracts_009/ill_typed/multiple_storage_and_code_fields.tz @@ -0,0 +1,7 @@ +parameter nat; +storage unit; +storage unit; +code { CAR; + DUP; NEG; ABS; COMPARE; ASSERT_EQ; + UNIT; NIL operation; PAIR }; +code {} \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/multiple_storage_field.tz b/tests_python/contracts_009/ill_typed/multiple_storage_field.tz new file mode 100644 index 0000000000000000000000000000000000000000..06c25f51d3b2087ef30c8d53b62121e47852bee3 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/multiple_storage_field.tz @@ -0,0 +1,6 @@ +parameter nat; +storage unit; +storage unit; +code { CAR; + DUP; NEG; ABS; COMPARE; ASSERT_EQ; + UNIT; NIL operation; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/never_literal.tz b/tests_python/contracts_009/ill_typed/never_literal.tz new file mode 100644 index 0000000000000000000000000000000000000000..ba36b3b5f20571dbe3f2ffd23cb255e58ce2c8ad --- /dev/null +++ b/tests_python/contracts_009/ill_typed/never_literal.tz @@ -0,0 +1,6 @@ +parameter unit; +storage unit; +code { + PUSH never {}; + FAILWITH + } diff --git a/tests_python/contracts_009/ill_typed/pack_big_map.tz b/tests_python/contracts_009/ill_typed/pack_big_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..29ae0d665051f298be07fa7d7b1e216e3551b362 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/pack_big_map.tz @@ -0,0 +1,7 @@ +parameter unit; +storage (pair (big_map int int) unit); +code { CDAR; + DUP; PACK; DROP; + UNIT; SWAP; PAIR; + NIL operation; + PAIR; } diff --git a/tests_python/contracts_009/ill_typed/pack_operation.tz b/tests_python/contracts_009/ill_typed/pack_operation.tz new file mode 100644 index 0000000000000000000000000000000000000000..349ca053af27cf00e200a29cb79b957e3ad51e68 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/pack_operation.tz @@ -0,0 +1,20 @@ +parameter unit; +storage unit; +code { DROP; + UNIT; # starting storage for contract + AMOUNT; # Push the starting balance + NONE key_hash; # No delegate + CREATE_CONTRACT # Create the contract + { parameter unit ; + storage unit ; + code + { CDR; + NIL operation; + PAIR; } }; + DIP { DROP }; + # invalid PACK + PACK; + DROP; + UNIT; + NIL operation; + PAIR; } diff --git a/tests_python/contracts_009/ill_typed/pack_sapling_state.tz b/tests_python/contracts_009/ill_typed/pack_sapling_state.tz new file mode 100644 index 0000000000000000000000000000000000000000..0524d9b27911d4cd4942a10bc349dffcd72c952b --- /dev/null +++ b/tests_python/contracts_009/ill_typed/pack_sapling_state.tz @@ -0,0 +1,13 @@ +# Verify SAPLING_STATE is not packable. The contract should not typecheck when using `PACK`. +# The lines below PACK are present only in case of PACK allows SAPLING_STATE to +# make the typechecker happy. +parameter unit; +storage (sapling_state 8); +code { UNPAIR; + DROP; + PACK; + DROP; + SAPLING_EMPTY_STATE 8; + NIL operation; + PAIR; + } diff --git a/tests_python/contracts_009/ill_typed/push_big_map_with_id_with_parens.tz b/tests_python/contracts_009/ill_typed/push_big_map_with_id_with_parens.tz new file mode 100644 index 0000000000000000000000000000000000000000..2c659e9a639d380a239084769604e7a9a2561be2 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/push_big_map_with_id_with_parens.tz @@ -0,0 +1,10 @@ +# This contract verifies it is not possible to use the instruction `PUSH big_map +# tk tv i` where i is the ID of an existing big_map +parameter int; +storage (big_map string nat); +code { UNPAIR; + DROP; + PUSH (big_map string nat) 0; + NIL operation; + PAIR + } \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/push_big_map_with_id_without_parens.tz b/tests_python/contracts_009/ill_typed/push_big_map_with_id_without_parens.tz new file mode 100644 index 0000000000000000000000000000000000000000..c5eeef97c7e353f13c4de228ebe02c7860d4b9f4 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/push_big_map_with_id_without_parens.tz @@ -0,0 +1,11 @@ +# This contract verifies it is not possible to use the instruction `PUSH big_map +# tk tv i` where i is the ID of an existing big_map +parameter int; +storage (big_map string nat); +code { + UNPAIR; + DROP; + PUSH big_map string nat 0; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/sapling_build_empty_state_with_int_parameter.tz b/tests_python/contracts_009/ill_typed/sapling_build_empty_state_with_int_parameter.tz new file mode 100644 index 0000000000000000000000000000000000000000..21b48391060bb0fde821b47c66068847c1f0dcc6 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/sapling_build_empty_state_with_int_parameter.tz @@ -0,0 +1,10 @@ +parameter nat; +storage (sapling_state 8); +code { + UNPAIR; + SWAP; + DROP; + SAPLING_EMPTY_STATE; + NIL operation; + PAIR; + }; diff --git a/tests_python/contracts_009/ill_typed/set_update_non_comparable.tz b/tests_python/contracts_009/ill_typed/set_update_non_comparable.tz new file mode 100644 index 0000000000000000000000000000000000000000..4a70691793c7609cc6958d2f309841b3ac06dffd --- /dev/null +++ b/tests_python/contracts_009/ill_typed/set_update_non_comparable.tz @@ -0,0 +1,9 @@ +# This contract tests the error message in case the UPDATE instruction on set +# is used with a non-comparable type +parameter (set nat); +storage unit; +code { CAR; + PUSH bool True; + NIL operation; + UPDATE; + UNIT; NIL operation; PAIR; } diff --git a/tests_python/contracts_009/ill_typed/ticket_apply.tz b/tests_python/contracts_009/ill_typed/ticket_apply.tz new file mode 100644 index 0000000000000000000000000000000000000000..a77fb08a6611f0d6ddaffdcba2f0108178d086b9 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/ticket_apply.tz @@ -0,0 +1,17 @@ +# This script attempts to duplicate a ticket by capturing it using APPLY. +# Is should fail at parsing because tickets are not packable so they are +# not allowed to be captured by APPLY. +parameter (ticket unit); +storage (option (pair (ticket unit) (ticket unit))); +code { + CAR; + LAMBDA (pair (ticket unit) unit) (ticket unit) { CAR }; + SWAP; APPLY; + DUP; + UNIT; EXEC; SWAP; + UNIT; EXEC; + PAIR; + SOME; + NIL operation; + PAIR + } diff --git a/tests_python/contracts_009/ill_typed/ticket_dup.tz b/tests_python/contracts_009/ill_typed/ticket_dup.tz new file mode 100644 index 0000000000000000000000000000000000000000..fee0ea3785bca57b3986a18cc0dbd72511ed889b --- /dev/null +++ b/tests_python/contracts_009/ill_typed/ticket_dup.tz @@ -0,0 +1,3 @@ +parameter (ticket %store nat) ; +storage unit; +code { UNPAIR; DUP; DROP 2; NIL operation; PAIR } diff --git a/tests_python/contracts_009/ill_typed/ticket_in_ticket.tz b/tests_python/contracts_009/ill_typed/ticket_in_ticket.tz new file mode 100644 index 0000000000000000000000000000000000000000..ee6bdf2387230414a3f5958d59f427bf9e3c1830 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/ticket_in_ticket.tz @@ -0,0 +1,16 @@ +# This script attempts to duplicate a ticket by storing it +# in another ticket and calling READ_TICKET twice on it. +# It should fail at parsing because ticket contents must be +# comparable so (ticket (ticket unit)) cannot be built. +parameter (ticket unit); +storage (option (pair (ticket unit) (ticket unit))); +code { + CAR; + PUSH nat 0; + SWAP; + TICKET; + READ_TICKET; CDR; CAR; + SWAP; READ_TICKET; CDR; CAR; + SWAP; DROP; + PAIR; SOME; NIL operation; PAIR + } \ No newline at end of file diff --git a/tests_python/contracts_009/ill_typed/ticket_unpack.tz b/tests_python/contracts_009/ill_typed/ticket_unpack.tz new file mode 100644 index 0000000000000000000000000000000000000000..888746f42eb0c4cb86b4f83c479c84201b00c12e --- /dev/null +++ b/tests_python/contracts_009/ill_typed/ticket_unpack.tz @@ -0,0 +1,5 @@ +# UNPACK on ticket should produce a type error +parameter unit; +storage (option (ticket nat)); +code { DROP ; PUSH nat 2 ; PACK ; UNPACK (ticket nat) ; + NIL operation ; PAIR } diff --git a/tests_python/contracts_009/ill_typed/uncomb0.tz b/tests_python/contracts_009/ill_typed/uncomb0.tz new file mode 100644 index 0000000000000000000000000000000000000000..9c3370912937e8dd1576984892adf39525f94e16 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/uncomb0.tz @@ -0,0 +1,3 @@ +parameter unit; +storage unit; +code { UNPAIR 0 } diff --git a/tests_python/contracts_009/ill_typed/uncomb1.tz b/tests_python/contracts_009/ill_typed/uncomb1.tz new file mode 100644 index 0000000000000000000000000000000000000000..6cc515335072d0263a2ec6b2304a059a9687fb4d --- /dev/null +++ b/tests_python/contracts_009/ill_typed/uncomb1.tz @@ -0,0 +1,3 @@ +parameter unit; +storage unit; +code { UNPAIR 1 } diff --git a/tests_python/contracts_009/ill_typed/unpack_sapling_state.tz b/tests_python/contracts_009/ill_typed/unpack_sapling_state.tz new file mode 100644 index 0000000000000000000000000000000000000000..a80f81eb84b6b3576768d0917812002ca4129ab9 --- /dev/null +++ b/tests_python/contracts_009/ill_typed/unpack_sapling_state.tz @@ -0,0 +1,12 @@ +# Verify SAPLING_STATE is not packable. The contract should not typecheck when using `UNPACK`. +# The lines below UNPACK are present only in case of UNPACK allows SAPLING_STATE to +# make the typechecker happy. +parameter bytes; +storage (unit); +code { CAR; + UNPACK (sapling_state 8); + DROP; + PUSH unit Unit; + NIL operation; + PAIR; + } diff --git a/tests_python/contracts_009/ill_typed/unpair_field_annotation_mismatch.tz b/tests_python/contracts_009/ill_typed/unpair_field_annotation_mismatch.tz new file mode 100644 index 0000000000000000000000000000000000000000..c2b3fe0a498de9736b30896f3a1bb633f8ec636f --- /dev/null +++ b/tests_python/contracts_009/ill_typed/unpair_field_annotation_mismatch.tz @@ -0,0 +1,10 @@ +parameter (unit :param_unit); +storage (unit :u1); +code { DROP ; + + UNIT @b; UNIT @a; PAIR %@ %@; + # Field annotations must match (or be ommited) + DUP; UNPAIR %c %d; DROP 2; + DROP; + + UNIT; NIL operation; PAIR } diff --git a/tests_python/contracts_009/legacy/create_account.tz b/tests_python/contracts_009/legacy/create_account.tz new file mode 100644 index 0000000000000000000000000000000000000000..7cd38465a10b13126860d2e5736820ee37c3f8df --- /dev/null +++ b/tests_python/contracts_009/legacy/create_account.tz @@ -0,0 +1,29 @@ +/* +- optional storage: the address of the created account +- param: Left [hash]: + + Create an account with manager [hash]; then perform a recursive call + on Right [addr] where [addr] is the address of the newly created + account. + + The created account has an initial balance of 100tz. It is not + delegatable. + +- param: Right [addr]: + + Check that the sender is self and that [addr] is a contract of type + [unit]. Finally store [addr]. + +*/ +parameter (or key_hash address) ; +storage (option address) ; +code { CAR; + IF_LEFT + { DIP { PUSH mutez 100000000 ; PUSH bool False ; NONE key_hash }; + CREATE_ACCOUNT ; + DIP { RIGHT key_hash ; DIP { SELF ; PUSH mutez 0 } ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS } ; + CONS ; NONE address ; SWAP ; PAIR } + { SELF ; ADDRESS ; SENDER ; IFCMPNEQ { FAIL } {} ; + DUP ; CONTRACT unit ; IF_SOME { DROP ; SOME } { FAIL } ; + NIL operation ; PAIR } } ; diff --git a/tests_python/contracts_009/legacy/create_contract.tz b/tests_python/contracts_009/legacy/create_contract.tz new file mode 100644 index 0000000000000000000000000000000000000000..a162044ac62bd8c00c25bef6726f1e77b1c8e9f2 --- /dev/null +++ b/tests_python/contracts_009/legacy/create_contract.tz @@ -0,0 +1,18 @@ +parameter (or key_hash address); +storage unit; +code { CAR; + IF_LEFT + { DIP { PUSH string "dummy"; + PUSH mutez 100000000 ; PUSH bool False ; + PUSH bool False ; NONE key_hash } ; + CREATE_CONTRACT + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } ; + DIP { RIGHT key_hash ; DIP { SELF ; PUSH mutez 0 } ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS } ; + CONS ; UNIT ; SWAP ; PAIR } + { SELF ; ADDRESS ; SENDER ; IFCMPNEQ { FAIL } {} ; + CONTRACT string ; IF_SOME {} { FAIL } ; + PUSH mutez 0 ; PUSH string "abcdefg" ; TRANSFER_TOKENS ; + NIL operation; SWAP; CONS ; UNIT ; SWAP ; PAIR } }; diff --git a/tests_python/contracts_009/legacy/create_contract_flags.tz b/tests_python/contracts_009/legacy/create_contract_flags.tz new file mode 100644 index 0000000000000000000000000000000000000000..888637dd726651c137f5c565176dca2a7488a7d2 --- /dev/null +++ b/tests_python/contracts_009/legacy/create_contract_flags.tz @@ -0,0 +1,26 @@ +parameter (pair key_hash (pair bool bool)); +storage unit; +code { CAR; + + UNPAPAIR @mgr @spendable @deletagable; + DIP { NONE @delegate key_hash } ; + DIIIIP { UNIT @init; + PUSH @credit mutez 100000000 ; + }; + # type of legacy create_contract + # :: key_hash : option key_hash : bool : bool : mutez : 'g : 'S + # -> operation : address : 'S + CREATE_CONTRACT + { parameter (string %default) ; + storage unit ; + code { DROP; UNIT ; NIL operation ; PAIR } } ; + # simulate create_contract but typecheck for dev + # DROP 6; + # PUSH address "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; + # NONE key_hash; SET_DELEGATE @origination; + DIP { DROP }; + + NIL operation; + SWAP; CONS; + UNIT; SWAP; PAIR + }; diff --git a/tests_python/contracts_009/legacy/create_contract_rootname.tz b/tests_python/contracts_009/legacy/create_contract_rootname.tz new file mode 100644 index 0000000000000000000000000000000000000000..13e24ae5cc24d3d24449a1e73b81ae585c0182b6 --- /dev/null +++ b/tests_python/contracts_009/legacy/create_contract_rootname.tz @@ -0,0 +1,18 @@ +parameter (or key_hash address); +storage unit; +code { CAR; + IF_LEFT + { DIP { PUSH string "dummy"; + PUSH mutez 100000000 ; PUSH bool False ; + PUSH bool False ; NONE key_hash } ; + CREATE_CONTRACT + { parameter (string %root) ; + storage string ; + code { CAR ; NIL operation ; PAIR } } ; + DIP { RIGHT key_hash ; DIP { SELF ; PUSH mutez 0 } ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS } ; + CONS ; UNIT ; SWAP ; PAIR } + { SELF ; ADDRESS ; SENDER ; IFCMPNEQ { FAIL } {} ; + CONTRACT string ; IF_SOME {} { FAIL } ; + PUSH mutez 0 ; PUSH string "abcdefg" ; TRANSFER_TOKENS ; + NIL operation; SWAP; CONS ; UNIT ; SWAP ; PAIR } }; diff --git a/tests_python/contracts_009/legacy/originator.tz b/tests_python/contracts_009/legacy/originator.tz new file mode 100644 index 0000000000000000000000000000000000000000..c454e230dc6d59e875ef3af6d0b43c04668e504a --- /dev/null +++ b/tests_python/contracts_009/legacy/originator.tz @@ -0,0 +1,16 @@ +parameter nat ; +storage (list address) ; +code + { DUP ; CAR ; PUSH nat 0 ; CMPNEQ ; + DIP { DUP ; CAR ; DIP { CDR ; NIL operation } } ; + LOOP + { PUSH mutez 5000000 ; + PUSH bool True ; # delegatable + NONE key_hash ; # delegate + PUSH key_hash "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ; # manager + CREATE_ACCOUNT ; + SWAP ; DIP { SWAP ; DIP { CONS } } ; + SWAP ; DIP { SWAP ; DIP { CONS } } ; + PUSH nat 1 ; SWAP ; SUB ; ABS ; + DUP ; PUSH nat 0 ; CMPNEQ } ; + DROP ; PAIR } diff --git a/tests_python/contracts_009/legacy/steps_to_quota.tz b/tests_python/contracts_009/legacy/steps_to_quota.tz new file mode 100644 index 0000000000000000000000000000000000000000..78e76e30893178a6b49b6aa057308fff81c8fdba --- /dev/null +++ b/tests_python/contracts_009/legacy/steps_to_quota.tz @@ -0,0 +1,12 @@ +parameter int ; +storage nat ; +code { CAR; + DUP; + GT; + LOOP { PUSH int 1; SWAP; SUB; DUP; GT; }; + DROP; + STEPS_TO_QUOTA; + # PUSH nat 1; + NIL operation; + PAIR; + }; diff --git a/tests_python/contracts_009/macros/assert.tz b/tests_python/contracts_009/macros/assert.tz new file mode 100644 index 0000000000000000000000000000000000000000..6c5ce503b55125f943459887c2c9e556a69a96a0 --- /dev/null +++ b/tests_python/contracts_009/macros/assert.tz @@ -0,0 +1,3 @@ +parameter bool; +storage unit; +code {CAR; ASSERT; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_cmpeq.tz b/tests_python/contracts_009/macros/assert_cmpeq.tz new file mode 100644 index 0000000000000000000000000000000000000000..55621bac8fe35939bb14d714a0753f92e9abcd66 --- /dev/null +++ b/tests_python/contracts_009/macros/assert_cmpeq.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; ASSERT_CMPEQ; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_cmpge.tz b/tests_python/contracts_009/macros/assert_cmpge.tz new file mode 100644 index 0000000000000000000000000000000000000000..e98b17044541c7d0588a38fd959cfeb24da90bec --- /dev/null +++ b/tests_python/contracts_009/macros/assert_cmpge.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; ASSERT_CMPGE; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_cmpgt.tz b/tests_python/contracts_009/macros/assert_cmpgt.tz new file mode 100644 index 0000000000000000000000000000000000000000..7a44174b7259acbda005701a838a353867adf930 --- /dev/null +++ b/tests_python/contracts_009/macros/assert_cmpgt.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; ASSERT_CMPGT; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_cmple.tz b/tests_python/contracts_009/macros/assert_cmple.tz new file mode 100644 index 0000000000000000000000000000000000000000..e4b61cfc44c3afde8de21e7aba4bd41e6c5c65dc --- /dev/null +++ b/tests_python/contracts_009/macros/assert_cmple.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; ASSERT_CMPLE; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_cmplt.tz b/tests_python/contracts_009/macros/assert_cmplt.tz new file mode 100644 index 0000000000000000000000000000000000000000..290b495378dfb980b2a93e19bd71ffcbdb5a76e8 --- /dev/null +++ b/tests_python/contracts_009/macros/assert_cmplt.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; ASSERT_CMPLT; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_cmpneq.tz b/tests_python/contracts_009/macros/assert_cmpneq.tz new file mode 100644 index 0000000000000000000000000000000000000000..86b601393b8c359db48d3d8ca6c4d2cfc5b90dad --- /dev/null +++ b/tests_python/contracts_009/macros/assert_cmpneq.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; ASSERT_CMPNEQ; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_eq.tz b/tests_python/contracts_009/macros/assert_eq.tz new file mode 100644 index 0000000000000000000000000000000000000000..338096a6277c00b53d8243640939e3c5f128e299 --- /dev/null +++ b/tests_python/contracts_009/macros/assert_eq.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; COMPARE; ASSERT_EQ; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_ge.tz b/tests_python/contracts_009/macros/assert_ge.tz new file mode 100644 index 0000000000000000000000000000000000000000..06bb3cec944b560d2a38aee333eae016814f1eb1 --- /dev/null +++ b/tests_python/contracts_009/macros/assert_ge.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; COMPARE; ASSERT_GE; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_gt.tz b/tests_python/contracts_009/macros/assert_gt.tz new file mode 100644 index 0000000000000000000000000000000000000000..d041093b0ebfa95c26c7b3457f36dc307c520947 --- /dev/null +++ b/tests_python/contracts_009/macros/assert_gt.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; COMPARE; ASSERT_GT; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_le.tz b/tests_python/contracts_009/macros/assert_le.tz new file mode 100644 index 0000000000000000000000000000000000000000..8250f3f3bdb19dc23172965d5d5f98645a461223 --- /dev/null +++ b/tests_python/contracts_009/macros/assert_le.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; COMPARE; ASSERT_LE; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_lt.tz b/tests_python/contracts_009/macros/assert_lt.tz new file mode 100644 index 0000000000000000000000000000000000000000..e387e9d740702326ddd50f53fa71b3e2188590aa --- /dev/null +++ b/tests_python/contracts_009/macros/assert_lt.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; COMPARE; ASSERT_LT; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/assert_neq.tz b/tests_python/contracts_009/macros/assert_neq.tz new file mode 100644 index 0000000000000000000000000000000000000000..83f19559e1d1a401500494b51edea556b25b006d --- /dev/null +++ b/tests_python/contracts_009/macros/assert_neq.tz @@ -0,0 +1,3 @@ +parameter (pair int int); +storage unit; +code {CAR; DUP; CAR; DIP{CDR}; COMPARE; ASSERT_NEQ; UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/big_map_get_add.tz b/tests_python/contracts_009/macros/big_map_get_add.tz new file mode 100644 index 0000000000000000000000000000000000000000..2dcf1ce69a08ac7b83d8d7f253475bb4b1c65a1b --- /dev/null +++ b/tests_python/contracts_009/macros/big_map_get_add.tz @@ -0,0 +1,7 @@ +parameter (pair (pair %set_pair int (option int)) (pair %check_pair int (option int))) ; +storage (pair (big_map int int) unit) ; +code { DUP ; DIP { CDAR } ; + DUP ; DIP { CADR; DUP ; CAR ; DIP { CDR } ; UPDATE ; DUP } ; + CADR ; DUP ; CDR ; DIP { CAR ; GET } ; + IF_SOME { SWAP ; IF_SOME { ASSERT_CMPEQ } {FAIL}} { ASSERT_NONE } ; + UNIT ; SWAP ; PAIR ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/macros/big_map_mem.tz b/tests_python/contracts_009/macros/big_map_mem.tz new file mode 100644 index 0000000000000000000000000000000000000000..55736ab89da6c3e1d3814e656fe6140796f71e3a --- /dev/null +++ b/tests_python/contracts_009/macros/big_map_mem.tz @@ -0,0 +1,5 @@ +# Fails if the boolean does not match the membership criteria +parameter (pair int bool) ; +storage (pair (big_map int unit) unit) ; +code { DUP ; DUP ; CADR ; DIP { CAAR ; DIP { CDAR ; DUP } ; MEM } ; + ASSERT_CMPEQ ; UNIT ; SWAP ; PAIR ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/macros/build_list.tz b/tests_python/contracts_009/macros/build_list.tz new file mode 100644 index 0000000000000000000000000000000000000000..842056d913ceb4abf344f835f1251d8f38a710d2 --- /dev/null +++ b/tests_python/contracts_009/macros/build_list.tz @@ -0,0 +1,6 @@ +parameter nat; +storage (list nat); +code { CAR @counter; NIL @acc nat; SWAP; DUP @cmp_num; PUSH nat 0; CMPNEQ; + LOOP { DUP; DIP {SWAP}; CONS @acc; SWAP; PUSH nat 1; SWAP; SUB @counter; + DUP; DIP{ABS}; PUSH int 0; CMPNEQ}; + CONS; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/macros/carn_and_cdrn.tz b/tests_python/contracts_009/macros/carn_and_cdrn.tz new file mode 100644 index 0000000000000000000000000000000000000000..cc3cdccee81a550781244d519eb00037c4b39df6 --- /dev/null +++ b/tests_python/contracts_009/macros/carn_and_cdrn.tz @@ -0,0 +1,26 @@ +# Same as ../opcodes/comb-get.tz but using the CAR n and CDR n macros instead of GET +parameter (pair nat nat nat unit); +storage unit; +code { + CAR ; + + # Checking the first element + DUP ; CAR ; + PUSH nat 1 ; ASSERT_CMPEQ ; + DUP ; CAR 0 ; + PUSH nat 1 ; ASSERT_CMPEQ ; + + # Checking the second element + DUP ; CAR 1 ; + PUSH nat 4 ; ASSERT_CMPEQ ; + + # Checking the third element + DUP ; CAR 2 ; + PUSH nat 2 ; ASSERT_CMPEQ ; + + # Checking the last (fourth) element + DUP ; CDR 3 ; + UNIT ; ASSERT_CMPEQ ; + + DROP ; UNIT ; NIL operation ; PAIR + } diff --git a/tests_python/contracts_009/macros/compare.tz b/tests_python/contracts_009/macros/compare.tz new file mode 100644 index 0000000000000000000000000000000000000000..698ef3e695ed3cdde0945e36dcdf79fe204df93c --- /dev/null +++ b/tests_python/contracts_009/macros/compare.tz @@ -0,0 +1,9 @@ +parameter (pair mutez mutez); +storage (list bool); +code {CAR; DUP; DUP; DUP; DUP; DIIIIIP {NIL bool}; + DIIIIP {DUP; CAR; DIP {CDR}; COMPARE; LE; CONS}; + DIIIP {DUP; CAR; DIP {CDR}; COMPARE; GE; CONS}; + DIIP{DUP; CAR; DIP {CDR}; COMPARE; LT; CONS}; + DIP {DUP; CAR; DIP {CDR}; COMPARE; GT; CONS}; + DUP; CAR; DIP {CDR}; COMPARE; EQ; CONS; + NIL operation; PAIR}; diff --git a/tests_python/contracts_009/macros/compare_bytes.tz b/tests_python/contracts_009/macros/compare_bytes.tz new file mode 100644 index 0000000000000000000000000000000000000000..3b5e5a9c400cfed1308c8bebe2e703d1c65f08c9 --- /dev/null +++ b/tests_python/contracts_009/macros/compare_bytes.tz @@ -0,0 +1,9 @@ +parameter (pair bytes bytes); +storage (list bool); +code {CAR; DUP; DUP; DUP; DUP; DIIIIIP {NIL bool}; + DIIIIP {DUP; CAR; DIP {CDR}; COMPARE; LE; CONS}; + DIIIP {DUP; CAR; DIP {CDR}; COMPARE; GE; CONS}; + DIIP{DUP; CAR; DIP {CDR}; COMPARE; LT; CONS}; + DIP {DUP; CAR; DIP {CDR}; COMPARE; GT; CONS}; + DUP; CAR; DIP {CDR}; COMPARE; EQ; CONS; + NIL operation; PAIR}; diff --git a/tests_python/contracts_009/macros/fail.tz b/tests_python/contracts_009/macros/fail.tz new file mode 100644 index 0000000000000000000000000000000000000000..7f8bde252130b0cfd39efde79d00d93aba6fce70 --- /dev/null +++ b/tests_python/contracts_009/macros/fail.tz @@ -0,0 +1,5 @@ +parameter unit; +storage unit; +code + { # This contract will never accept a incoming transaction + FAIL}; diff --git a/tests_python/contracts_009/macros/guestbook.tz b/tests_python/contracts_009/macros/guestbook.tz new file mode 100644 index 0000000000000000000000000000000000000000..b362f94b957ec7a9277c0d6a282fd64a0a8098bf --- /dev/null +++ b/tests_python/contracts_009/macros/guestbook.tz @@ -0,0 +1,10 @@ +parameter string; +storage (map address (option string)); + +code { UNPAIR @message @guestbook; SWAP; + DUP; SENDER; GET @previous_message; + ASSERT_SOME; + ASSERT_NONE; + SWAP; SOME; SOME; SENDER; UPDATE; + NIL operation; + PAIR } diff --git a/tests_python/contracts_009/macros/macro_annotations.tz b/tests_python/contracts_009/macros/macro_annotations.tz new file mode 100644 index 0000000000000000000000000000000000000000..f48f18e3d942de1445d6e93c8b4a29d63441bba2 --- /dev/null +++ b/tests_python/contracts_009/macros/macro_annotations.tz @@ -0,0 +1,6 @@ +parameter unit; +storage (pair (unit %truc) unit); +code { DROP; UNIT ; UNIT ; PAIR %truc ; UNIT ; + DUUP @new_storage ; + DIP { DROP ; DROP } ; + NIL operation ; PAIR } diff --git a/tests_python/contracts_009/macros/map_caddaadr.tz b/tests_python/contracts_009/macros/map_caddaadr.tz new file mode 100644 index 0000000000000000000000000000000000000000..45509839cc0110159db2409a2df3635bd5c71f7b --- /dev/null +++ b/tests_python/contracts_009/macros/map_caddaadr.tz @@ -0,0 +1,4 @@ +parameter unit; +storage (pair (pair nat (pair nat (pair (pair (pair (nat %p) (mutez %value)) nat) nat))) nat); +code { MAP_CDADDAADR @new_storage %value { PUSH mutez 1000000 ; ADD } ; + NIL operation ; SWAP; SET_CAR }; diff --git a/tests_python/contracts_009/macros/max_in_list.tz b/tests_python/contracts_009/macros/max_in_list.tz new file mode 100644 index 0000000000000000000000000000000000000000..89c4955e937426236f5e5666560530c5f41969ac --- /dev/null +++ b/tests_python/contracts_009/macros/max_in_list.tz @@ -0,0 +1,9 @@ +parameter (list int); +storage (option int); +code {CAR; DIP{NONE int}; + ITER {SWAP; + IF_NONE {SOME} + {DIP {DUP}; DUP; DIP{SWAP}; + CMPLE; IF {DROP} {DIP {DROP}}; + SOME}}; + NIL operation; PAIR}; diff --git a/tests_python/contracts_009/macros/min.tz b/tests_python/contracts_009/macros/min.tz new file mode 100644 index 0000000000000000000000000000000000000000..cedd835bbac866f1abe37a5b030e93943dec4bfd --- /dev/null +++ b/tests_python/contracts_009/macros/min.tz @@ -0,0 +1,11 @@ + +parameter (pair int int); +storage int; +code { CAR; # Ignore the storage + DUP; # Duplicate so we can get both the numbers passed as parameters + DUP; # Second dup so we can access the lesser number + CAR; DIP{CDR}; # Unpack the numbers on top of the stack + CMPLT; # Compare the two numbers, placing a boolean on top of the stack + IF {CAR} {CDR}; # Access the first number if the boolean was true + NIL operation; # Return no op + PAIR} # Pair the numbers satisfying the calling convention diff --git a/tests_python/contracts_009/macros/pair_macro.tz b/tests_python/contracts_009/macros/pair_macro.tz new file mode 100644 index 0000000000000000000000000000000000000000..55c70a3be3e9b5113c5a3666a96930abb970576e --- /dev/null +++ b/tests_python/contracts_009/macros/pair_macro.tz @@ -0,0 +1,6 @@ +parameter unit; +storage unit; +code { UNIT; UNIT; UNIT; UNIT; UNIT; + PAPAPAPAIR @name %x1 %x2 %x3 %x4 %x5; + CDDDAR %x4 @fourth; + DROP; CDR; NIL operation; PAIR} diff --git a/tests_python/contracts_009/macros/set_caddaadr.tz b/tests_python/contracts_009/macros/set_caddaadr.tz new file mode 100644 index 0000000000000000000000000000000000000000..e98671e409899c405474340b8caa8211c9518ea9 --- /dev/null +++ b/tests_python/contracts_009/macros/set_caddaadr.tz @@ -0,0 +1,5 @@ +parameter mutez; +storage (pair (pair nat (pair nat (pair (pair (pair (nat %p) (mutez %value)) nat) nat))) nat); +code { DUP ; CAR ; SWAP ; CDR ; + SET_CADDAADR @toplevel_pair_name %value ; + NIL operation ; PAIR }; diff --git a/tests_python/contracts_009/macros/take_my_money.tz b/tests_python/contracts_009/macros/take_my_money.tz new file mode 100644 index 0000000000000000000000000000000000000000..bb502d0418494c23807b6b826a6b0e560279b7a2 --- /dev/null +++ b/tests_python/contracts_009/macros/take_my_money.tz @@ -0,0 +1,9 @@ +parameter key_hash; +storage unit; +code { CAR; IMPLICIT_ACCOUNT; # Create an account for the recipient of the funds + DIP{UNIT}; # Push a value of the storage type below the contract + PUSH mutez 1000000; # The person can have a ꜩ + UNIT; # Push the contract's argument type + TRANSFER_TOKENS; # Run the transfer + NIL operation; SWAP; CONS; + PAIR }; # Cleanup and put the return values diff --git a/tests_python/contracts_009/macros/unpair_macro.tz b/tests_python/contracts_009/macros/unpair_macro.tz new file mode 100644 index 0000000000000000000000000000000000000000..384b6839d88bbd3430c3ca70986b9c333a033c7a --- /dev/null +++ b/tests_python/contracts_009/macros/unpair_macro.tz @@ -0,0 +1,9 @@ +parameter (unit :param_unit); +storage (unit :u1); +code { DROP ; + UNIT :u4 @a4; UNIT :u3 @a3; UNIT :u2 @a2; UNIT :u1 @a1; + PAIR; UNPAIR @x1 @x2; + PPAIPAIR @p1 %x1 %x2 %x3 %x4; UNPPAIPAIR %x1 % %x3 %x4 @uno @due @tre @quattro; + PAPAPAIR @p2 %x1 %x2 %x3 %x4; UNPAPAPAIR @un @deux @trois @quatre; + PAPPAIIR @p3 %x1 %x2 %x3 %x4; UNPAPPAIIR @one @two @three @four; + DIP { DROP; DROP; DROP }; NIL operation; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/mini_scenarios/authentication.tz b/tests_python/contracts_009/mini_scenarios/authentication.tz new file mode 100644 index 0000000000000000000000000000000000000000..021bbd26361a4c38df8cc3a2c7d0748f9ad6420a --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/authentication.tz @@ -0,0 +1,30 @@ +/* + +This contract is an example of using a cryptographic signature to +handle authentication. A public key is stored, and only the owner of +the secret key associated to this public key can interact with the +contract. She is allowed to perform any list of operations by sending +them wrapped in a lambda to the contract with a cryptographic +signature. + +To ensure that each signature is used only once and is not replayed by +an attacker, not only the lambda is signed but also the unique +identifier of the contract (a pair of the contract address and the +chain id) and a counter that is incremented at each successful call. + +More precisely, the signature should check against pack ((chain_id, +self) (param, counter)). + +*/ +parameter (pair (lambda unit (list operation)) signature); +storage (pair (nat %counter) key); +code + { + UNPPAIPAIR; + DUUUP; DUUP ; SELF; CHAIN_ID ; PPAIPAIR; PACK; + DIP { SWAP }; DUUUUUP ; DIP { SWAP }; + DUUUP; DIP {CHECK_SIGNATURE}; SWAP; IF {DROP} {FAILWITH}; + UNIT; EXEC; + DIP { PUSH nat 1; ADD }; + PAPAIR + } diff --git a/tests_python/contracts_009/mini_scenarios/big_map_entrypoints.tz b/tests_python/contracts_009/mini_scenarios/big_map_entrypoints.tz new file mode 100644 index 0000000000000000000000000000000000000000..d49e6257167affbe689e6b4654ccfdf4cc828240 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/big_map_entrypoints.tz @@ -0,0 +1,31 @@ +storage + (pair (big_map string nat) (big_map string nat)) ; +parameter + (or (unit %default) + (or (or %mem (string %mem_left) (string %mem_right)) + (or (or %add (pair %add_left string nat) (pair %add_right string nat)) + (or %rem (string %rem_left) (string %rem_right))))) ; +code { UNPAIR ; + IF_LEFT + { DROP ; + DUP ; CAR ; + PUSH mutez 0 ; + NONE key_hash ; + CREATE_CONTRACT + { parameter string ; + storage (big_map string nat) ; + code { UNPAIR ; DROP ; NIL operation ; PAIR }} ; + DIP { DROP } ; + NIL operation ; SWAP ; CONS ; PAIR } + { IF_LEFT + { IF_LEFT + { DIP { UNPAIR } ; DIP { DUP } ; MEM ; ASSERT } + { DIP { UNPAIR ; SWAP } ; DIP { DUP } ; MEM ; ASSERT ; SWAP } } + { IF_LEFT + { IF_LEFT + { UNPAIR ; DIIP { UNPAIR } ; DIP { SOME } ; UPDATE } + { UNPAIR ; DIIP { UNPAIR ; SWAP } ; DIP { SOME } ; UPDATE ; SWAP } } + { IF_LEFT + { DIP { UNPAIR } ; DIP { NONE nat } ; UPDATE } + { DIP { UNPAIR ; SWAP } ; DIP { NONE nat } ; UPDATE ; SWAP } } } ; + PAIR ; NIL operation ; PAIR } } diff --git a/tests_python/contracts_009/mini_scenarios/big_map_magic.tz b/tests_python/contracts_009/mini_scenarios/big_map_magic.tz new file mode 100644 index 0000000000000000000000000000000000000000..f4e36f639bff585fc876dc87fa08cd2e575b1a38 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/big_map_magic.tz @@ -0,0 +1,41 @@ +# this contracts handles two big_maps +storage + (or (pair (big_map string string) (big_map string string)) unit) ; +parameter + # it has 5 entry points + # swap: swaps the two maps. + (or (unit %swap) + # reset: resets storage, either to a new pair of maps, or to unit + (or (or %reset (pair (big_map string string) (big_map string string)) unit) + # import: drops the existing storage and creates two maps + # from the given lists of string pairs. + (or (pair %import (list (pair string string)) (list (pair string string))) + # add: adds the given list of key - value pairs into the + # first map + (or (list %add (pair string string)) + # rem: removes the given list of key - value pairs + # from the first map + (list %rem string))))) ; +code { UNPAIR ; + IF_LEFT + { DROP ; ASSERT_LEFT ; UNPAIR ; SWAP ; PAIR ; LEFT unit } + { IF_LEFT + { SWAP ; DROP } + { IF_LEFT + { DIP { ASSERT_RIGHT ; DROP } ; + UNPAIR ; + DIP { EMPTY_BIG_MAP string string } ; + ITER { UNPAIR ; DIP { SOME } ; UPDATE } ; + SWAP ; + DIP { EMPTY_BIG_MAP string string } ; + ITER { UNPAIR ; DIP { SOME } ; UPDATE } ; + SWAP ; + PAIR ; LEFT unit } + { IF_LEFT + { DIP { ASSERT_LEFT ; UNPAIR } ; + ITER { UNPAIR ; DIP { SOME } ; UPDATE } ; + PAIR ; LEFT unit } + { DIP { ASSERT_LEFT ; UNPAIR } ; + ITER { DIP { NONE string } ; UPDATE } ; + PAIR ; LEFT unit } }} } ; + NIL operation ; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/mini_scenarios/big_map_read.tz b/tests_python/contracts_009/mini_scenarios/big_map_read.tz new file mode 100644 index 0000000000000000000000000000000000000000..60d666e28f29cf8122fd51bba5dc7f6d92569be1 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/big_map_read.tz @@ -0,0 +1,9 @@ +storage (nat); +parameter (big_map nat nat); +code { CAR; + PUSH nat 1; + GET; + ASSERT_SOME; + NIL operation; + PAIR; + } diff --git a/tests_python/contracts_009/mini_scenarios/big_map_store.tz b/tests_python/contracts_009/mini_scenarios/big_map_store.tz new file mode 100644 index 0000000000000000000000000000000000000000..4dc68145a69186faeb3e05f9f92344a52e8d1f39 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/big_map_store.tz @@ -0,0 +1,8 @@ +storage (big_map nat nat); +parameter (unit); +code { DROP; + EMPTY_BIG_MAP nat nat; + NIL operation; + PAIR; + } + diff --git a/tests_python/contracts_009/mini_scenarios/big_map_write.tz b/tests_python/contracts_009/mini_scenarios/big_map_write.tz new file mode 100644 index 0000000000000000000000000000000000000000..bde3b19baa3d24fb6b27722c03469fd7d584dbb5 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/big_map_write.tz @@ -0,0 +1,10 @@ +storage (unit); +parameter (big_map nat nat); +code { UNPAIR ; + PUSH (option nat) (Some 1); + PUSH nat 1; + UPDATE; + DROP; + NIL operation; + PAIR; + } diff --git a/tests_python/contracts_009/mini_scenarios/create_contract.tz b/tests_python/contracts_009/mini_scenarios/create_contract.tz new file mode 100644 index 0000000000000000000000000000000000000000..0d09a1fdfca61fdf33504ef20bdc9d0d209b6aaf --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/create_contract.tz @@ -0,0 +1,33 @@ +/* +- param: None: + + Create a contract then perform a recursive call on Some [addr] where + [addr] is the address of the newly created contract. + + The created contract simply stores its parameter (a string). It is + initialized with the storage "dummy" and has an initial balance of + 100tz. It has no delegate so these 100tz are totally frozen. + +- param: Some [addr]: + + Check that the sender is self, call the contract at address [addr] + with param "abcdefg" transferring 0tz. + +*/ +parameter (option address) ; +storage unit ; +code { CAR ; + IF_NONE + { PUSH string "dummy" ; + PUSH mutez 100000000 ; NONE key_hash ; + CREATE_CONTRACT + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } ; + DIP { SOME ; DIP { SELF ; PUSH mutez 0 } ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS } ; + CONS ; UNIT ; SWAP ; PAIR } + { SELF ; ADDRESS ; SENDER ; IFCMPNEQ { FAIL } {} ; + CONTRACT string ; IF_SOME {} { FAIL } ; + PUSH mutez 0 ; PUSH string "abcdefg" ; TRANSFER_TOKENS ; + NIL operation; SWAP; CONS ; UNIT ; SWAP ; PAIR } } ; \ No newline at end of file diff --git a/tests_python/contracts_009/mini_scenarios/create_contract_simple.tz b/tests_python/contracts_009/mini_scenarios/create_contract_simple.tz new file mode 100644 index 0000000000000000000000000000000000000000..2a5185d748895a41bd9552103d42176ff965baea --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/create_contract_simple.tz @@ -0,0 +1,14 @@ +parameter unit; +storage unit; +code { CAR; + PUSH string "foo"; + PUSH mutez 0; + NONE key_hash; + CREATE_CONTRACT + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } ; + DROP; DROP; + NIL operation; + PAIR; + } diff --git a/tests_python/contracts_009/mini_scenarios/default_account.tz b/tests_python/contracts_009/mini_scenarios/default_account.tz new file mode 100644 index 0000000000000000000000000000000000000000..74e7693d7ba52ecc77d7b20e24590cbae32570cd --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/default_account.tz @@ -0,0 +1,9 @@ +/* +Send 100 tz to the implicit account given as parameter. +*/ + +parameter key_hash; +storage unit; +code {DIP{UNIT}; CAR; IMPLICIT_ACCOUNT; + PUSH mutez 100000000; UNIT; TRANSFER_TOKENS; + NIL operation; SWAP; CONS; PAIR} diff --git a/tests_python/contracts_009/mini_scenarios/execution_order_appender.tz b/tests_python/contracts_009/mini_scenarios/execution_order_appender.tz new file mode 100644 index 0000000000000000000000000000000000000000..9a519f7809241e9c5c5673ceea6d16bce690888d --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/execution_order_appender.tz @@ -0,0 +1,17 @@ +# Given a storage (adr, str), calls the contract at adr with the +# parameter str +parameter unit; +storage (pair address string); +code { + CDR; + DUP; + UNPAIR; + CONTRACT string; + ASSERT_SOME; + PUSH mutez 0; + DIG 2; + TRANSFER_TOKENS; + NIL operation; + SWAP; + CONS; + PAIR }; diff --git a/tests_python/contracts_009/mini_scenarios/execution_order_caller.tz b/tests_python/contracts_009/mini_scenarios/execution_order_caller.tz new file mode 100644 index 0000000000000000000000000000000000000000..ead37544f4e867228b608e8df54ca64dab776381 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/execution_order_caller.tz @@ -0,0 +1,17 @@ +# Given storage [adr1; ...; adrn], emits operations +# [ TRANSFER_TOKENS Unit (Mutez 0) adr1 ; +# ... ; +# TRANSFER_TOKENS Unit (Mutez 0) adrn ] +parameter unit; +storage (list address); +code { + CDR; + DUP; + MAP { + CONTRACT unit; + ASSERT_SOME; + PUSH mutez 0; + UNIT; + TRANSFER_TOKENS; + }; + PAIR }; diff --git a/tests_python/contracts_009/mini_scenarios/execution_order_storer.tz b/tests_python/contracts_009/mini_scenarios/execution_order_storer.tz new file mode 100644 index 0000000000000000000000000000000000000000..2bfc7505e9cd5f95b5f9116e00ab8f633beefa0b --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/execution_order_storer.tz @@ -0,0 +1,4 @@ +# Appends the parameter to the string in storage +parameter (string); +storage (string); +code { UNPAIR; SWAP; CONCAT; NIL operation; PAIR }; diff --git a/tests_python/contracts_009/mini_scenarios/groth16.tz b/tests_python/contracts_009/mini_scenarios/groth16.tz new file mode 100644 index 0000000000000000000000000000000000000000..66ff23a5e73bc18e116e63b09c645b220a48d2ee --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/groth16.tz @@ -0,0 +1,74 @@ +# The contract returns if the proof verifies, and fails otherwise. +# The verifying key, proof, and inputs are generated from +# ZoKrates, modified to use BLS12-381. +# The circuit proves knowledge of a square root of 113569. +storage unit; + +# The parameter is a pair consisting of: +# * A pair of Fr element inputs, x and y +# * A proof, consisting of +# * G1 points `a` and `c` +# * G2 point `b` +parameter (pair (pair (bls12_381_fr %input_x) (bls12_381_fr %input_y)) + (pair (pair (bls12_381_g1 %proof_a) (bls12_381_g2 %proof_b)) + (bls12_381_g1 %proof_c))); + +code + { + # Discard storage and unpair. Result stack should be + # input{x:y} : proof{a:b:c}. + CAR; UNPPAIPPAIIR; + + # Push the verifying key. Result stack should be + # input{x:y} + # : proof{a:b:c} + # : vk_{a:b:gamma:delta:gamma_{a:b:c}} + DIP 5 + { + PUSH @vk_gamma_c bls12_381_g1 0x063bd6e11e2fcaac1dd8cf68c6b1925a73c3c583e298ed37c41c3715115cf96358a42dbe85a0228cbfd8a6c8a8c54cd015b5ae2860d1cc47f84698d951f14d9448d03f04df2ca0ffe609a2067d6f1a892163a5e05e541279134cae52b1f23c6b; + + PUSH @vk_gamma_b bls12_381_g1 0x11f5b5db1da7f1f26217edcce2219d016003af6e5b4d1ca3ad0ff477e354717e658bf16beddc4f4fb76ce39d3327811e0601709dc7ed98c70463cfa1ba33f99851b52b51d1a042d7425bec6277287441c399973632445ce61e7fdd63a70f0f60; + + PUSH @vk_gamma_a bls12_381_g1 0x03535a322edd23c55b0ca025e54d450d95df49cc9ee873dcd500e8219f4771264bf159b3b105954d85c7bea8ffe1ea0400c767fe58989366c2837fba76f1b4f46644f19be8ad01e22d894b649e427e0d7e04677ee3919d982f0f96bb0a2f0c34; + + PUSH @vk_delta bls12_381_g2 0x10c6d5cdca84fc3c7f33061add256f48e0ab03a697832b338901898b650419eb6f334b28153fb73ad2ecd1cd2ac67053161e9f46cfbdaf7b1132a4654a55162850249650f9b873ac3113fa8c02ef1cd1df481480a4457f351d28f4da89d19fa405c3d77f686dc9a24d2681c9184bf2b091f62e6b24df651a3da8bd7067e14e7908fb02f8955b84af5081614cb5bc49b416d9edf914fc608c441b3f2eb8b6043736ddb9d4e4d62334a23b5625c14ef3e1a7e99258386310221b22d83a5eac035c; + + PUSH @vk_gamma bls12_381_g2 0x16dcbd28bff336c2649c7dd1d8391ac7ce6f7ef0124a9db7a4a485a124199eded7ce963c1c18aee1eca9994fe06f192c00e0fb653e1fc737d8d0e2f2f91424ca01f6e6e7c5c04f1c43db03a2900cf6b942aaed6ae77daea6200e094b78c38d770028d531a9d1a118ec23d5a39be7aa6dc28f778da1988856d2235c4a35e81fa48380f050d4baf7ebd7b5e058bf294da916afc34562f097c02a8fcbcf62a00de44f8ae6cfa7acb8ad254e3aeea8b2af12f65b7ee0f54855cb9bd432f3436f238f; + + PUSH @vk_b bls12_381_g2 0x0e9383f98df2c6e8b5b45f3876c3384596a0cdbc41349f83c4380bf463a050cdbd1d5057aa483a642e66486d1ed7362a1869e423c3877095e215c17282b11108601166f928043254bbce603bf86f4cec9f2e97e9660e98e4f5bce9b2b3bbacb40946b702ccfcc9a31e0bfc1543a2128edcc95807740a2310ae25eb47b935648e392c58dfae5b5e899d3b970d64e4e9e209741ea8bfedcfcc16b3fd890ff02c788ec0943feaaf01bbb354317acb85fcfd611133e4e563d53ca4e0f50e21cf2e7e; + + PUSH @vk_a bls12_381_g1 0x1040577c7d349e332735fc947c868c24a665f812f5dc1e7f60e65e2df80be2267a4b7341ed2287285fccd517acd96d910abba947235c364553aa6445f2f2b3a1a728225a330286ba5197ab87f0edc560d89fc7b623812f7d0d633341726e597a + }; + + # Compute vk_x as + # (vk_gamma_b * input_x) + (vk_gamma_c * input_y) + vk_gamma_a + # Result stack should be + # vk_x + # : input{x:y} + # : proof{a:b:c} + # : vk_{a:b:gamma:delta:gamma_{a:b:c}} + DUP; DUP 12; MUL; + DUP 3; DUP 14; MUL; + ADD; DUP 11; ADD @vk_x; + + # Push the list for the pairing check. The list should be + # [ (proof_a, proof_b); + # (-vk_x, vk_gamma); + # (-proof_c, vk_delta); + # (-vk_a, vk_b) ] + NIL (pair bls12_381_g1 bls12_381_g2); + DUP 9; DUP 9; NEG; PAIR; CONS; + DUP 11; DUP 8; NEG; PAIR; CONS; + DUP 10; DUP 3; NEG; PAIR; CONS; + DUP 6; DUP 6; PAIR; CONS; + + # Compute the pairing check and fail if it doesn't succeed + PAIRING_CHECK; ASSERT; + + # Drop the stack + DROP 13; + + # return no operations + UNIT; NIL operation; PAIR + + } diff --git a/tests_python/contracts_009/mini_scenarios/hardlimit.tz b/tests_python/contracts_009/mini_scenarios/hardlimit.tz new file mode 100644 index 0000000000000000000000000000000000000000..464062a521666ca7dab981011aa2e23456c91ddd --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/hardlimit.tz @@ -0,0 +1,5 @@ +parameter unit ; +storage int ; +code { # This contract stops accepting transactions after N incoming transactions + CDR ; DUP ; PUSH int 0 ; CMPLT; IF {PUSH int -1 ; ADD} {FAIL}; + NIL operation ; PAIR} ; diff --git a/tests_python/contracts_009/mini_scenarios/lockup.tz b/tests_python/contracts_009/mini_scenarios/lockup.tz new file mode 100644 index 0000000000000000000000000000000000000000..a8ff43aa0f85135758a41c0c073ab5cf75211bdc --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/lockup.tz @@ -0,0 +1,19 @@ +parameter unit; +storage (pair timestamp (pair mutez address)); +code { CDR; # Ignore the parameter + DUP; # Duplicate the storage + CAR; # Get the timestamp + NOW; # Push the current timestamp + CMPLT; # Compare to the current time + IF {FAIL} {}; # Fail if it is too soon + DUP; # Duplicate the storage value + # this must be on the bottom of the stack for us to call transfer tokens + CDR; # Ignore the timestamp, focussing in on the transfer data + DUP; # Duplicate the transfer information + CAR; # Get the amount of the transfer on top of the stack + DIP{CDR}; # Put the contract underneath it + DIP { CONTRACT unit ; ASSERT_SOME } ; + UNIT; # Put the contract's argument type on top of the stack + TRANSFER_TOKENS; # Emit the transfer + NIL operation; SWAP; CONS;# Make a singleton list of internal operations + PAIR} # Pair up to meet the calling convention diff --git a/tests_python/contracts_009/mini_scenarios/multiple_en2.tz b/tests_python/contracts_009/mini_scenarios/multiple_en2.tz new file mode 100644 index 0000000000000000000000000000000000000000..a1acafd48706d86b5bbd614f2922d52b109edf10 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/multiple_en2.tz @@ -0,0 +1,77 @@ +{ parameter unit ; + storage (option address) ; + code { SENDER ; + SELF ; + ADDRESS ; + { COMPARE ; + EQ ; + IF { CDR ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + DIP { NIL operation } ; + DUP ; + CONTRACT %add unit ; + { IF_NONE {} { { UNIT ; FAILWITH } } } ; + DUP ; + CONTRACT %fact nat ; + { IF_NONE {} { { UNIT ; FAILWITH } } } ; + DUP ; + CONTRACT %add nat ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + PUSH mutez 0 ; + PUSH nat 12 ; + TRANSFER_TOKENS ; + SWAP ; + DIP { CONS } ; + DUP ; + CONTRACT unit ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + PUSH mutez 0 ; + PUSH unit Unit ; + TRANSFER_TOKENS ; + SWAP ; + DIP { CONS } ; + DUP ; + CONTRACT %sub nat ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + PUSH mutez 0 ; + PUSH nat 3 ; + TRANSFER_TOKENS ; + SWAP ; + DIP { CONS } ; + DUP ; + CONTRACT %add nat ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + PUSH mutez 0 ; + PUSH nat 5 ; + TRANSFER_TOKENS ; + SWAP ; + DIP { CONS } ; + DROP ; + DIP { NONE address } ; + PAIR } + { CAR ; + DUP ; + DIP { DIP { PUSH int 0 ; PUSH mutez 0 ; NONE key_hash } ; + DROP ; + CREATE_CONTRACT + { parameter (or (or (nat %add) (nat %sub)) (unit %default)) ; + storage int ; + code { AMOUNT ; + PUSH mutez 0 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + { { DUP ; CAR ; DIP { CDR } } } ; + IF_LEFT + { IF_LEFT { ADD } { SWAP ; SUB } } + { DROP ; DROP ; PUSH int 0 } ; + NIL operation ; + PAIR } } } ; + DIP { SELF ; PUSH mutez 0 } ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + SWAP ; + CONS ; + DIP { SOME } ; + PAIR } } + } } diff --git a/tests_python/contracts_009/mini_scenarios/multiple_entrypoints_counter.tz b/tests_python/contracts_009/mini_scenarios/multiple_entrypoints_counter.tz new file mode 100644 index 0000000000000000000000000000000000000000..740190697171aa8c5944e5b361127d75d5ba74aa --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/multiple_entrypoints_counter.tz @@ -0,0 +1,29 @@ +{ parameter unit ; + storage (option address) ; + code { SENDER ; SELF ; ADDRESS ; + IFCMPEQ + { CDR ; ASSERT_SOME ; + DIP { NIL operation } ; + DUP ; CONTRACT %add unit ; ASSERT_NONE ; + DUP ; CONTRACT %fact nat ; ASSERT_NONE ; + DUP ; CONTRACT %add nat ; ASSERT_SOME ; PUSH mutez 0 ; PUSH nat 12 ; TRANSFER_TOKENS ; SWAP ; DIP { CONS } ; + DUP ; CONTRACT unit ; ASSERT_SOME ; PUSH mutez 0 ; PUSH unit Unit ; TRANSFER_TOKENS ; SWAP ; DIP { CONS } ; + DUP ; CONTRACT %sub nat ; ASSERT_SOME ; PUSH mutez 0 ; PUSH nat 3 ; TRANSFER_TOKENS ; SWAP ; DIP { CONS } ; + DUP ; CONTRACT %add nat ; ASSERT_SOME ; PUSH mutez 0 ; PUSH nat 5 ; TRANSFER_TOKENS ; SWAP ; DIP { CONS } ; + DROP ; DIP { NONE address } ; PAIR } + { CAR ; DUP ; + DIP + { DIP { PUSH int 0 ; PUSH mutez 0 ; NONE key_hash } ; + DROP ; + CREATE_CONTRACT + { parameter (or (or (nat %add) (nat %sub)) (unit %default)) ; + storage int ; + code { AMOUNT ; PUSH mutez 0 ; ASSERT_CMPEQ ; + UNPAIR ; + IF_LEFT + { IF_LEFT { ADD } { SWAP ; SUB } } + { DROP ; DROP ; PUSH int 0 } ; + NIL operation ; PAIR } } } ; + DIP { SELF ; PUSH mutez 0 } ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; SWAP ; CONS ; + DIP { SOME } ; PAIR } } } \ No newline at end of file diff --git a/tests_python/contracts_009/mini_scenarios/parameterized_multisig.tz b/tests_python/contracts_009/mini_scenarios/parameterized_multisig.tz new file mode 100644 index 0000000000000000000000000000000000000000..16f785ae0a25bdc083b9f2997cc3648299a45d66 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/parameterized_multisig.tz @@ -0,0 +1,24 @@ +storage (pair bool (pair (map nat (pair bool bool)) (pair key key))); +parameter (or nat (pair signature nat)); +code { DUP; CAR; DIP{CDDR}; # Stack tangling + IF_LEFT { DIP{DUP; CAR}; GET; # Get the value stored for that index + IF_NONE { PUSH bool False} # If not referenced, reject + { DUP; CAR; DIP{CDR}; AND}; + PAIR} + { DUP; CAR; DIP{CDR; DUP; PACK ; BLAKE2B}; PAIR; SWAP; # Create the signature pair + DIP{ DIP{DUP; CDR; DIP{CAR}; DUP}; + SWAP; CAR; DIP{DUP; UNPAIR}; CHECK_SIGNATURE }; # Check the first signature + SWAP; + # If the signature typechecked, get and update the first element of the pair + IF { DIP{DROP; SWAP; DUP}; DUP; + DIP{ GET; IF_NONE{PUSH (pair bool bool) (Pair False False)} {}; + CDR; PUSH bool True; PAIR; SOME }} + # Check the second signature + { DIP{DIP{DUP; CDR}; SWAP; DIP {UNPAIR}; CHECK_SIGNATURE}; SWAP; + IF { DUP; DIP{DIP{SWAP; DUP}; GET}; SWAP; + IF_NONE {PUSH (pair bool bool) (Pair False False)} {}; + CAR; PUSH bool True; SWAP; PAIR; SOME; SWAP} + {FAIL}}; + # Update the stored value and finish off + UPDATE; PAIR; PUSH bool False; PAIR}; + NIL operation; PAIR } diff --git a/tests_python/contracts_009/mini_scenarios/replay.tz b/tests_python/contracts_009/mini_scenarios/replay.tz new file mode 100644 index 0000000000000000000000000000000000000000..e03ac4ab211338314847258c31eafc1ff2c5a8e8 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/replay.tz @@ -0,0 +1,8 @@ +# This contract always fail because it tries to execute twice the same operation +parameter unit ; +storage unit ; +code { CDR ; NIL operation ; + SOURCE ; CONTRACT unit ; ASSERT_SOME ; + PUSH mutez 1 ; UNIT ; TRANSFER_TOKENS ; + DUP ; DIP { CONS } ; CONS ; + PAIR } diff --git a/tests_python/contracts_009/mini_scenarios/reveal_signed_preimage.tz b/tests_python/contracts_009/mini_scenarios/reveal_signed_preimage.tz new file mode 100644 index 0000000000000000000000000000000000000000..1a7e97eb8a68cd7d89b28be6b243107b18494c2f --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/reveal_signed_preimage.tz @@ -0,0 +1,13 @@ +parameter (pair bytes signature) ; +storage (pair bytes key) ; +code { + #check that sha256(param.bytes) == storage.bytes + DUP ; UNPAIR ; CAR; SHA256; DIP { CAR } ; ASSERT_CMPEQ ; + + # check that the sig is a valid signature of the preimage + DUP ; UNPAIR ; SWAP ; DIP { UNPAIR ; SWAP } ; CDR ; CHECK_SIGNATURE ; ASSERT ; + + # send all our tokens to the implicit account corresponding to the stored public key + CDR ; DUP ; CDR ; HASH_KEY ; IMPLICIT_ACCOUNT ; + BALANCE ; UNIT ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/mini_scenarios/self_address_receiver.tz b/tests_python/contracts_009/mini_scenarios/self_address_receiver.tz new file mode 100644 index 0000000000000000000000000000000000000000..6ebda8daad9e128ab4b731cb5dd3ff3a15038a88 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/self_address_receiver.tz @@ -0,0 +1,12 @@ +# See self_address_sender.tz +parameter (lambda unit address); +storage unit; +code { + UNPAIR; + UNIT; + EXEC; + SELF_ADDRESS; + ASSERT_CMPEQ; + NIL operation; + PAIR + } diff --git a/tests_python/contracts_009/mini_scenarios/self_address_sender.tz b/tests_python/contracts_009/mini_scenarios/self_address_sender.tz new file mode 100644 index 0000000000000000000000000000000000000000..b0f74073c2ff27c3e01ce13d08f2935706faba5f --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/self_address_sender.tz @@ -0,0 +1,17 @@ +# This tests that the SELF_ADDRESS inside a lambda returns the address +# of the contract executing the lambda (not the contract defining it). +# To do so, two contracts called the sender and the receiver are used. +# The sender (this contract) sends the lambda { DROP; SELF_ADDRESS } +# to the receiver (see self_address_receiver.tz) who checks that the +# returned value is the same as its SELF_ADDRESS. +parameter (contract (lambda unit address)); +storage unit; +code { + CAR; + BALANCE; + LAMBDA unit address { DROP; SELF_ADDRESS }; + TRANSFER_TOKENS; + DIP { UNIT; NIL operation }; + CONS; + PAIR + } diff --git a/tests_python/contracts_009/mini_scenarios/ticket_builder_fungible.tz b/tests_python/contracts_009/mini_scenarios/ticket_builder_fungible.tz new file mode 100644 index 0000000000000000000000000000000000000000..674ae800771d99747ed8b1939bc4dcdcac588f19 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/ticket_builder_fungible.tz @@ -0,0 +1,40 @@ +## A simple fungible token contract implemented using tickets of type +## [ticket unit]. + +## To store and transfer the tokens see ticket_wallet_fungible.tz + +## For non-fungible tokens, see ticket_builder_non_fungible.tz + +parameter (or (ticket %burn unit) (pair %mint (contract %destination (ticket unit)) (nat %amount))); +storage address; +code + { + AMOUNT; PUSH mutez 0; ASSERT_CMPEQ; + + UNPAIR; + IF_LEFT + { + # Burn entrypoint + + # Check that the ticket is ticketed by ourselves + READ_TICKET; CAR; SELF_ADDRESS; ASSERT_CMPEQ; + + # Drop the ticket + DROP; + + # Finish + NIL operation + } + { + # Mint entrypoint + + # Authenticate SENDER + DUP @manager 2; SENDER; ASSERT_CMPEQ; + + UNPAIR; + SWAP; UNIT; TICKET; + PUSH mutez 0; SWAP; TRANSFER_TOKENS; + NIL operation; SWAP; CONS + }; + PAIR + } diff --git a/tests_python/contracts_009/mini_scenarios/ticket_builder_non_fungible.tz b/tests_python/contracts_009/mini_scenarios/ticket_builder_non_fungible.tz new file mode 100644 index 0000000000000000000000000000000000000000..ae669d17ad60e0225a8562ef8365321d95af3eff --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/ticket_builder_non_fungible.tz @@ -0,0 +1,47 @@ +## A simple non-fungible token contract implemented using tickets of +## type [ticket nat] with amounts of 1. + +## To store and transfer the tokens see ticket_wallet_non_fungible.tz + +## For fungible tokens, see ticket_builder_fungible.tz + +parameter (or (ticket %burn nat) (contract %mint_destination (ticket nat))); +storage (pair (address %manager) (nat %counter)); +code + { + AMOUNT; PUSH mutez 0; ASSERT_CMPEQ; + + UNPAIR 3; + IF_LEFT + { + # Burn entrypoint + + # Check that the ticket is ticketed by ourselves + READ_TICKET; CAR; SELF_ADDRESS; ASSERT_CMPEQ; + + # Drop the ticket + DROP; + + # Finish + NIL operation + } + { + # Mint entrypoint + + # Authenticate SENDER + DUP @manager 2; SENDER; ASSERT_CMPEQ; + + # Mint the token + PUSH @amount nat 1; + DUP @counter 4; + TICKET; + + # Send it + PUSH mutez 0; SWAP; TRANSFER_TOKENS; + NIL operation; SWAP; CONS; + + # Increment counter + DIP 2 {PUSH nat 1; ADD}; + }; + PAIR 3 + } diff --git a/tests_python/contracts_009/mini_scenarios/ticket_wallet_fungible.tz b/tests_python/contracts_009/mini_scenarios/ticket_wallet_fungible.tz new file mode 100644 index 0000000000000000000000000000000000000000..d04180ddb8994be007cb1bacb6c94d7a32c36e29 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/ticket_wallet_fungible.tz @@ -0,0 +1,88 @@ +## A simple wallet for fungible tokens implemented using tickets of +## type [ticket unit]. + +## For actually minting or burning the tokens, see ticket_builder_fungible.tz + +## For non-fungible tokens, see ticket_wallet_non_fungible.tz + +parameter (or (ticket %receive unit) (pair %send (contract %destination (ticket unit)) (nat %amount) (address %ticketer))); +storage (pair (address %manager) (big_map %tickets address (ticket unit))); +code + { + AMOUNT; PUSH mutez 0; ASSERT_CMPEQ; + + UNPAIR 3; + IF_LEFT + { + # Receive entrypoint + + # Get the ticketer + READ_TICKET; CAR @ticketer; DUP; + + # Extract the associated ticket, if any, from the stored big map + DIG 4; + NONE (ticket unit); + DIG 2; + GET_AND_UPDATE; + + # Join it with the parameter + IF_SOME + { + DIG 3; + PAIR; + JOIN_TICKETS; + ASSERT_SOME + } + { DIG 2 }; + SOME; + DIG 2; + GET_AND_UPDATE; + ASSERT_NONE; + SWAP; + PAIR; + NIL operation + } + { + # Send entrypoints + + # Authenticate SENDER + DUP @manager 2; SENDER; ASSERT_CMPEQ; + + UNPAIR 3; + + # Get the ticket associated to the requested ticketer + DIG 4; + NONE (ticket unit); + DUP @ticketer 5; + GET_AND_UPDATE; + ASSERT_SOME; + + # Substract the requested amount + READ_TICKET; + GET @total_amount 4; + DUP @amount 5; + SWAP; SUB; ISNAT; ASSERT_SOME @remaining_amount; + + # Split the ticket + DIG 4; PAIR; SWAP; SPLIT_TICKET; + ASSERT_SOME; UNPAIR @to_send @to_keep; + + # Store the ticket to keep + DUG 5; + SOME; + DIG 3; + GET_AND_UPDATE; + ASSERT_NONE; + DIG 2; PAIR; + + # Send the ticket + SWAP; + PUSH mutez 0; + DIG 3; + TRANSFER_TOKENS; + NIL operation; + SWAP; + CONS; + }; + PAIR + } diff --git a/tests_python/contracts_009/mini_scenarios/ticket_wallet_non_fungible.tz b/tests_python/contracts_009/mini_scenarios/ticket_wallet_non_fungible.tz new file mode 100644 index 0000000000000000000000000000000000000000..ba0170ae830e29b600f5793301247ec81d1bf203 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/ticket_wallet_non_fungible.tz @@ -0,0 +1,61 @@ +## A simple wallet for non-fungible tokens implemented using tickets +## of type [ticket nat]. + +## For each nat [n], the ticketer is assumed to produce at most one +## ticket containing [n] and to always use amounts of exactly one. + +## For fungible tokens, see ticket_wallet_fungible.tz + +parameter (or (ticket %receive nat) (pair %send (contract %destination (ticket nat)) (address %ticketer) (nat %id))); +storage (pair (address %manager) (big_map %tickets (pair address nat) (ticket nat))); +code + { + AMOUNT; PUSH mutez 0; ASSERT_CMPEQ; + + UNPAIR 3; + IF_LEFT + { + # Receive entrypoint + + # Get the ticketer and id + READ_TICKET; CAST (pair (address %ticketer) (nat %id) (nat %amount)); + UNPAIR 3; + DIG 2; PUSH nat 1; ASSERT_CMPEQ; # This checks that the amount is 1 + PAIR; + + # Extract the associated ticket, if any, from the stored big map + DIP {SOME; DIP {SWAP}}; + GET_AND_UPDATE; + ASSERT_NONE; + + SWAP; + PAIR; + NIL operation + } + { + # Send entrypoints + + # Authenticate SENDER + DUP @manager 2; SENDER; ASSERT_CMPEQ; + + UNPAIR; + + # Get the ticket associated to the requested ticketer and id + DIG 3; + NONE (ticket nat); + DIG 3; + GET_AND_UPDATE; + ASSERT_SOME; + + SWAP; DIG 3; PAIR; DUG 2; + + # Send the ticket + PUSH mutez 0; + SWAP; + TRANSFER_TOKENS; + NIL operation; + SWAP; + CONS; + }; + PAIR + } diff --git a/tests_python/contracts_009/mini_scenarios/vote_for_delegate.tz b/tests_python/contracts_009/mini_scenarios/vote_for_delegate.tz new file mode 100644 index 0000000000000000000000000000000000000000..1155c073f5880a581976cb8c3463251025c7bbd9 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/vote_for_delegate.tz @@ -0,0 +1,30 @@ +parameter (option key_hash) ; +storage (pair + (pair %mgr1 (address %addr) (option %key key_hash)) + (pair %mgr2 (address %addr) (option %key key_hash))) ; +code { # Update the storage + DUP ; CDAAR %addr @%; SENDER ; PAIR %@ %@; UNPAIR; + IFCMPEQ + { UNPAIR ; SWAP ; SET_CADR %key @changed_mgr1_key } + { DUP ; CDDAR ; SENDER ; + IFCMPEQ + { UNPAIR ; SWAP ; SET_CDDR %key } + { FAIL } } ; + # Now compare the proposals + DUP ; CADR ; + DIP { DUP ; CDDR } ; + IF_NONE + { IF_NONE + { NONE key_hash ; + SET_DELEGATE ; NIL operation ; SWAP ; CONS } + { DROP ; NIL operation } } + { SWAP ; + IF_SOME + { DIP { DUP } ; + IFCMPEQ + { SOME ; + SET_DELEGATE ; NIL operation ; SWAP ; CONS } + { DROP ; + NIL operation }} + { DROP ; NIL operation }} ; + PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/mini_scenarios/weather_insurance.tz b/tests_python/contracts_009/mini_scenarios/weather_insurance.tz new file mode 100644 index 0000000000000000000000000000000000000000..e7e99e0183355889dd9bbf2087d4a885e550c37d --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/weather_insurance.tz @@ -0,0 +1,19 @@ +parameter (pair (signature %signed_weather_data) (nat :rain %actual_level)); +# (pair (under_key over_key) (pair weather_service_key (pair rain_level days_in_future))) +storage (pair (pair (address %under_key) + (address %over_key)) + (pair (nat :rain %rain_level) (key %weather_service_key))); +code { DUP; DUP; + CAR; MAP_CDR{PACK ; BLAKE2B}; + SWAP; CDDDR %weather_service_key; + DIP {UNPAIR} ; CHECK_SIGNATURE @sigok; # Check if the data has been correctly signed + ASSERT; # If signature is not correct, end the execution + DUP; DUP; DUP; DIIIP{CDR %storage}; # Place storage type on bottom of stack + DIIP{CDAR}; # Place contracts below numbers + DIP{CADR %actual_level}; # Get actual rain + CDDAR %rain_level; # Get rain threshold + CMPLT; IF {CAR %under_key} {CDR %over_key}; # Select contract to receive tokens + CONTRACT unit ; ASSERT_SOME ; + BALANCE; UNIT ; TRANSFER_TOKENS @trans.op; # Setup and execute transfer + NIL operation ; SWAP ; CONS ; + PAIR }; diff --git a/tests_python/contracts_009/mini_scenarios/xcat.tz b/tests_python/contracts_009/mini_scenarios/xcat.tz new file mode 100644 index 0000000000000000000000000000000000000000..83e6c7ac1d50fb81328152ca69aba539c96934b3 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/xcat.tz @@ -0,0 +1,48 @@ +parameter (bytes); +storage (unit); +code { + # Extract parameter from initial stack. + CAR @preimage; + DIP { + # Push contract constants to the stack. + # + # There's a temptation to use @storage to parametrize + # a contract but, in general, there's no reason to encumber + # @storage with immutable values. + PUSH @from key_hash "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; #changeme + IMPLICIT_ACCOUNT ; + PUSH @to key_hash "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN"; #changeme + IMPLICIT_ACCOUNT ; + PUSH @target_hash bytes 0x123456; #changeme + PUSH @deadline timestamp "2018-08-08 00:00:00Z"; #changeme + }; + # Test if the deadline has passed. + SWAP; NOW; + IFCMPLT + # In case the deadline did pass: + { + # Ignore parameter, just transfer xtz balance back to @from + DROP; DROP; DROP; BALANCE; UNIT; TRANSFER_TOKENS; + } + # In case the deadline hasn't passed yet: + { + # Test length of parameter. + DUP; SIZE; + PUSH @max_length nat 32; + IFCMPLT + { PUSH string "preimage too long"; FAILWITH; } + { + # Test if it's a preimage of @target_hash. + SHA256 @candidate_hash; + IFCMPNEQ + { PUSH string "invalid preimage"; FAILWITH; } + { + # Transfer xtz balance to @to. + BALANCE; UNIT; TRANSFER_TOKENS; DIP { DROP }; + }; + }; + }; + # Transform single operation into a list. + NIL operation; SWAP; CONS; + UNIT; SWAP; PAIR + } diff --git a/tests_python/contracts_009/mini_scenarios/xcat_dapp.tz b/tests_python/contracts_009/mini_scenarios/xcat_dapp.tz new file mode 100644 index 0000000000000000000000000000000000000000..86ca62c5ac500e4e9679822fa6951eb93696b004 --- /dev/null +++ b/tests_python/contracts_009/mini_scenarios/xcat_dapp.tz @@ -0,0 +1,79 @@ +parameter (or + # First possible action is funding, to create an xcat + (pair %fund + (address %dest) + (pair %settings (bytes %target_hash) (timestamp %deadline))) + + # Other possible action is to claim the tokens (or ask a refund) + (or %claim_refund + (bytes %preimage_claim) + (bytes %refund_hash))); + +storage (pair + (big_map + bytes # The target hash is used as a key + (pair + # We store in %from the person who funded the xcat + (pair %recipients (address %from) (address %dest)) + (pair %settings (mutez %amount) (timestamp %deadline))) + ) + unit); + +code { + NIL @operations operation; SWAP; + UNPAPAIR @% @% @%; DIP {DUP}; + IF_LEFT # Let's fund a new xcat! + { + # Unpack the parameters + UNPAIR @% @%; + # Assert that the destination address is of type unit. + # This costs a bit more gas but limits foot-shooting. + DUP; CONTRACT @dest unit; ASSERT_SOME; DROP; + SWAP; UNPAIR @% @%; + DIP + { + AMOUNT @amount; + SENDER; + DUP; CONTRACT @from unit; ASSERT_SOME; DROP; + DIP { PAIR; SWAP; }; PAIR; PAIR; SOME @xcat; + SWAP; + }; + DUP; DIP { MEM; NOT; ASSERT }; # Assert that this target hash isn't already in the map + UPDATE; PAIR @new_storage; SWAP; PAIR; + } + { + # Let's process a claim or a refund + IF_LEFT + { # It's a claim! + DUP; SIZE; PUSH nat 32; ASSERT_CMPGE; + SHA256 @hash; DUP; DIP {SWAP}; + DIIP { + GET; ASSERT_SOME; + # Check deadline and prepare transaction. + DUP; CADR @%; CONTRACT @dest unit; ASSERT_SOME; + SWAP; CDR @%; + UNPAIR @% @%; SWAP; + # The deadline must not have passed + NOW; ASSERT_CMPLT; + # prepare transaction + UNIT; TRANSFER_TOKENS; + }; + } + { # It's a refund! + DUP; + DIP + { + GET; ASSERT_SOME; + DUP; CAAR @%; CONTRACT @from unit; ASSERT_SOME; SWAP; CDR; + UNPAIR @% @%; SWAP; + # The deadline must not HAVE passed + NOW; ASSERT_CMPGE; + UNIT; TRANSFER_TOKENS; SWAP; + }; + }; + # Clear the big map + NONE @none (pair (pair address address) (pair mutez timestamp)); + SWAP; UPDATE @cleared_map; SWAP; DIP { PAIR; SWAP }; + CONS; PAIR; + } + } \ No newline at end of file diff --git a/tests_python/contracts_009/non_regression/bug_262.tz b/tests_python/contracts_009/non_regression/bug_262.tz new file mode 100644 index 0000000000000000000000000000000000000000..63475c5ac18525abe6c0467098039ba75a4e2edc --- /dev/null +++ b/tests_python/contracts_009/non_regression/bug_262.tz @@ -0,0 +1,5 @@ +{ parameter unit ; + storage unit ; + code { DROP ; + LAMBDA unit unit {} ; UNIT ; EXEC ; + NIL operation ; PAIR } } \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/abs.tz b/tests_python/contracts_009/opcodes/abs.tz new file mode 100644 index 0000000000000000000000000000000000000000..d03d0883fe73e67ec19a02e24365c00ab583a0d7 --- /dev/null +++ b/tests_python/contracts_009/opcodes/abs.tz @@ -0,0 +1,5 @@ +parameter nat; +storage unit; +code { CAR; + DUP; NEG; ABS; COMPARE; ASSERT_EQ; + UNIT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/add.tz b/tests_python/contracts_009/opcodes/add.tz new file mode 100644 index 0000000000000000000000000000000000000000..cbefea08a7a422651a01695368440733b093eb05 --- /dev/null +++ b/tests_python/contracts_009/opcodes/add.tz @@ -0,0 +1,25 @@ +parameter unit; +storage unit; +code + { + CAR; + + PUSH int 2; PUSH int 2; ADD; PUSH int 4; ASSERT_CMPEQ; + PUSH int 2; PUSH int 2; ADD; PUSH int 4; ASSERT_CMPEQ; + PUSH int 2; PUSH nat 2; ADD; PUSH int 4; ASSERT_CMPEQ; + PUSH nat 2; PUSH int 2; ADD; PUSH int 4; ASSERT_CMPEQ; + PUSH nat 2; PUSH nat 2; ADD; PUSH nat 4; ASSERT_CMPEQ; + + # Offset a timestamp by 60 seconds + PUSH int 60; PUSH timestamp "2019-09-09T12:08:37Z"; ADD; + PUSH timestamp "2019-09-09T12:09:37Z"; ASSERT_CMPEQ; + + PUSH timestamp "2019-09-09T12:08:37Z"; PUSH int 60; ADD; + PUSH timestamp "2019-09-09T12:09:37Z"; ASSERT_CMPEQ; + + PUSH mutez 1000; PUSH mutez 1000; ADD; + PUSH mutez 2000; ASSERT_CMPEQ; + + NIL operation; + PAIR; + } diff --git a/tests_python/contracts_009/opcodes/add_bls12_381_fr.tz b/tests_python/contracts_009/opcodes/add_bls12_381_fr.tz new file mode 100644 index 0000000000000000000000000000000000000000..e7b60dedc9328cd6282e7776307c2d95fd077d96 --- /dev/null +++ b/tests_python/contracts_009/opcodes/add_bls12_381_fr.tz @@ -0,0 +1,3 @@ +parameter (pair bls12_381_fr bls12_381_fr); +storage (option (bls12_381_fr)); +code {CAR; UNPAIR; ADD; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/add_bls12_381_g1.tz b/tests_python/contracts_009/opcodes/add_bls12_381_g1.tz new file mode 100644 index 0000000000000000000000000000000000000000..9f817c88d8a5a378b9cbb7fe5e11d293cefd4683 --- /dev/null +++ b/tests_python/contracts_009/opcodes/add_bls12_381_g1.tz @@ -0,0 +1,3 @@ +parameter (pair bls12_381_g1 bls12_381_g1); +storage (option (bls12_381_g1)); +code {CAR; UNPAIR; ADD; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/add_bls12_381_g2.tz b/tests_python/contracts_009/opcodes/add_bls12_381_g2.tz new file mode 100644 index 0000000000000000000000000000000000000000..1d1c0688c1d225d64b1a7a7b9e4944ee8909cf7a --- /dev/null +++ b/tests_python/contracts_009/opcodes/add_bls12_381_g2.tz @@ -0,0 +1,3 @@ +parameter (pair bls12_381_g2 bls12_381_g2); +storage (option (bls12_381_g2)); +code {CAR; UNPAIR; ADD; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/add_delta_timestamp.tz b/tests_python/contracts_009/opcodes/add_delta_timestamp.tz new file mode 100644 index 0000000000000000000000000000000000000000..b9ed869017260e360e9ec04d534d31792041ca98 --- /dev/null +++ b/tests_python/contracts_009/opcodes/add_delta_timestamp.tz @@ -0,0 +1,3 @@ +parameter (pair int timestamp); +storage (option timestamp); +code { CAR; DUP; CAR; DIP{CDR}; ADD; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/add_timestamp_delta.tz b/tests_python/contracts_009/opcodes/add_timestamp_delta.tz new file mode 100644 index 0000000000000000000000000000000000000000..766bf9f91f51a7482e0256c9ca7bcad7247fc86b --- /dev/null +++ b/tests_python/contracts_009/opcodes/add_timestamp_delta.tz @@ -0,0 +1,3 @@ +parameter (pair timestamp int); +storage (option timestamp); +code { CAR; DUP; CAR; DIP{CDR}; ADD; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/address.tz b/tests_python/contracts_009/opcodes/address.tz new file mode 100644 index 0000000000000000000000000000000000000000..7e6bcdec337b40cdd784165818713bccc652d6f4 --- /dev/null +++ b/tests_python/contracts_009/opcodes/address.tz @@ -0,0 +1,3 @@ +parameter (contract unit); +storage (option address); +code {CAR; ADDRESS; SOME; NIL operation; PAIR } diff --git a/tests_python/contracts_009/opcodes/and.tz b/tests_python/contracts_009/opcodes/and.tz new file mode 100644 index 0000000000000000000000000000000000000000..48e346ca04f36dcf762b47f25e6eb642542ee99d --- /dev/null +++ b/tests_python/contracts_009/opcodes/and.tz @@ -0,0 +1,3 @@ +parameter (pair :param (bool %first) (bool %second)); +storage (option bool); +code { CAR ; UNPAIR; AND @and; SOME @res; NIL @noop operation; PAIR; UNPAIR @x @y; PAIR %a %b }; diff --git a/tests_python/contracts_009/opcodes/and_binary.tz b/tests_python/contracts_009/opcodes/and_binary.tz new file mode 100644 index 0000000000000000000000000000000000000000..96f60082c713bcefd9eca89e2f890a8251ce8c78 --- /dev/null +++ b/tests_python/contracts_009/opcodes/and_binary.tz @@ -0,0 +1,27 @@ +parameter unit; +storage unit; +code { DROP; + + # 0101 & 0110 = 0100 + PUSH nat 5; PUSH nat 6; AND; PUSH nat 4; ASSERT_CMPEQ; + + # 0110 & 0101 = 0100 + PUSH nat 6; PUSH int 5; AND; PUSH nat 4; ASSERT_CMPEQ; + + # Negative numbers are represented as with a initial virtual + # infinite series of 1's. + # Hence, AND with -1 (1111...) is identity: + + # 12 = ...1100 + # & -1 = ...1111 + # ---- + # = 12 = ...1100 + PUSH nat 12; PUSH int -1; AND; PUSH nat 12; ASSERT_CMPEQ; + + # 12 = ...0001100 + # & -5 = ...1111011 + # ----------------- + # 8 = ...0001000 + PUSH nat 12; PUSH int -5; AND; PUSH nat 8; ASSERT_CMPEQ; + + UNIT; NIL @noop operation; PAIR; }; diff --git a/tests_python/contracts_009/opcodes/and_logical_1.tz b/tests_python/contracts_009/opcodes/and_logical_1.tz new file mode 100644 index 0000000000000000000000000000000000000000..20743c0bfdf9118f513ee58d7191c94ec2a71be8 --- /dev/null +++ b/tests_python/contracts_009/opcodes/and_logical_1.tz @@ -0,0 +1,3 @@ +parameter (pair bool bool); +storage bool; +code { CAR ; UNPAIR; AND @and; NIL @noop operation; PAIR; }; diff --git a/tests_python/contracts_009/opcodes/balance.tz b/tests_python/contracts_009/opcodes/balance.tz new file mode 100644 index 0000000000000000000000000000000000000000..0a9bfc61494cbed495a37534976b26df6dae9229 --- /dev/null +++ b/tests_python/contracts_009/opcodes/balance.tz @@ -0,0 +1,3 @@ +parameter unit; +storage mutez; +code {DROP; BALANCE; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/big_map_mem_nat.tz b/tests_python/contracts_009/opcodes/big_map_mem_nat.tz new file mode 100644 index 0000000000000000000000000000000000000000..71ecaf2c4a754ea20a1f802f0e3c6401914a7e5e --- /dev/null +++ b/tests_python/contracts_009/opcodes/big_map_mem_nat.tz @@ -0,0 +1,7 @@ +parameter nat; +storage (pair (big_map nat nat) (option bool)) ; +# stores (map, Some flag) where flag = parameter is a member of +# the map in first component of storage +code { UNPAIR; + DIP { CAR; DUP }; + MEM; SOME; SWAP; PAIR; NIL operation; PAIR;} diff --git a/tests_python/contracts_009/opcodes/big_map_mem_string.tz b/tests_python/contracts_009/opcodes/big_map_mem_string.tz new file mode 100644 index 0000000000000000000000000000000000000000..8c557f7dc1f8ff5ee260794ab094576252c56724 --- /dev/null +++ b/tests_python/contracts_009/opcodes/big_map_mem_string.tz @@ -0,0 +1,7 @@ +parameter string; +storage (pair (big_map string nat) (option bool)) ; +# stores (map, Some flag) where flag = parameter is a member of +# the map in first component of storage +code { UNPAIR; + DIP { CAR; DUP }; + MEM; SOME; SWAP; PAIR; NIL operation; PAIR;} diff --git a/tests_python/contracts_009/opcodes/big_map_to_self.tz b/tests_python/contracts_009/opcodes/big_map_to_self.tz new file mode 100644 index 0000000000000000000000000000000000000000..6a9442b9f3e5e149af21b348323b212ad8ea664c --- /dev/null +++ b/tests_python/contracts_009/opcodes/big_map_to_self.tz @@ -0,0 +1,22 @@ +parameter (or (pair %have_fun (big_map string nat) unit) (unit %default)); +storage (big_map string nat); +code { + UNPAIR; + DIP {NIL operation}; + IF_LEFT { + DROP + } + { + DROP; + SELF %have_fun; + PUSH mutez 0; + DUP 4; + PUSH (option nat) (Some 8); + PUSH string "hahaha"; + UPDATE; + UNIT; SWAP; PAIR; + TRANSFER_TOKENS; + CONS + }; + PAIR + } diff --git a/tests_python/contracts_009/opcodes/bls12_381_fr_push_bytes_not_padded.tz b/tests_python/contracts_009/opcodes/bls12_381_fr_push_bytes_not_padded.tz new file mode 100644 index 0000000000000000000000000000000000000000..fd4142914d2cd7180cdeebe9200555669e2d2133 --- /dev/null +++ b/tests_python/contracts_009/opcodes/bls12_381_fr_push_bytes_not_padded.tz @@ -0,0 +1,9 @@ +parameter unit; +storage (option bls12_381_fr); +code { + DROP; + PUSH bls12_381_fr 0x00; + SOME; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/bls12_381_fr_push_nat.tz b/tests_python/contracts_009/opcodes/bls12_381_fr_push_nat.tz new file mode 100644 index 0000000000000000000000000000000000000000..314b97f2a6b99b8140aca3ef58dbd32027053a53 --- /dev/null +++ b/tests_python/contracts_009/opcodes/bls12_381_fr_push_nat.tz @@ -0,0 +1,9 @@ +parameter unit; +storage (option bls12_381_fr); +code { + DROP; + PUSH bls12_381_fr 16; + SOME; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/bls12_381_fr_to_int.tz b/tests_python/contracts_009/opcodes/bls12_381_fr_to_int.tz new file mode 100644 index 0000000000000000000000000000000000000000..67e2c9b080b1c342d8402134edf892a3db5d2932 --- /dev/null +++ b/tests_python/contracts_009/opcodes/bls12_381_fr_to_int.tz @@ -0,0 +1,8 @@ +parameter bls12_381_fr; +storage int; +code { + CAR; + INT; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/bls12_381_fr_to_mutez.tz b/tests_python/contracts_009/opcodes/bls12_381_fr_to_mutez.tz new file mode 100644 index 0000000000000000000000000000000000000000..39630958e51504f44803811eb9e0b3242981543c --- /dev/null +++ b/tests_python/contracts_009/opcodes/bls12_381_fr_to_mutez.tz @@ -0,0 +1,12 @@ +parameter bls12_381_fr; +storage mutez; +code { + CAR; + INT; + ISNAT; + ASSERT_SOME; + PUSH mutez 1; + MUL; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/bls12_381_fr_z_int.tz b/tests_python/contracts_009/opcodes/bls12_381_fr_z_int.tz new file mode 100644 index 0000000000000000000000000000000000000000..67018c55fabae6d65dec6b0712a25fa0cd4e0a94 --- /dev/null +++ b/tests_python/contracts_009/opcodes/bls12_381_fr_z_int.tz @@ -0,0 +1,8 @@ +parameter int; +storage (bls12_381_fr); +code { + UNPAIR; + MUL; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/bls12_381_fr_z_nat.tz b/tests_python/contracts_009/opcodes/bls12_381_fr_z_nat.tz new file mode 100644 index 0000000000000000000000000000000000000000..1376e0c395614cccaa7ca9232510eec9d9eb436f --- /dev/null +++ b/tests_python/contracts_009/opcodes/bls12_381_fr_z_nat.tz @@ -0,0 +1,8 @@ +parameter nat; +storage (bls12_381_fr); +code { + UNPAIR; + MUL; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/bls12_381_z_fr_int.tz b/tests_python/contracts_009/opcodes/bls12_381_z_fr_int.tz new file mode 100644 index 0000000000000000000000000000000000000000..783fb3c0d66070dd3c836e38cced65594145a66a --- /dev/null +++ b/tests_python/contracts_009/opcodes/bls12_381_z_fr_int.tz @@ -0,0 +1,9 @@ +parameter int; +storage (bls12_381_fr); +code { + UNPAIR; + SWAP; + MUL; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/bls12_381_z_fr_nat.tz b/tests_python/contracts_009/opcodes/bls12_381_z_fr_nat.tz new file mode 100644 index 0000000000000000000000000000000000000000..1210e36db0e1d7dc532170164e827917bdf36676 --- /dev/null +++ b/tests_python/contracts_009/opcodes/bls12_381_z_fr_nat.tz @@ -0,0 +1,9 @@ +parameter nat; +storage (bls12_381_fr); +code { + UNPAIR; + SWAP; + MUL; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/bytes.tz b/tests_python/contracts_009/opcodes/bytes.tz new file mode 100644 index 0000000000000000000000000000000000000000..e4dd8445eecc5d0e836e873bcf1a3e747f4004f6 --- /dev/null +++ b/tests_python/contracts_009/opcodes/bytes.tz @@ -0,0 +1,11 @@ +# A contract that accepts bytes in a default entry point and does nothing. +# Useful for testing transfers of arbitrary sizes. +parameter bytes; +storage unit; +code + { + CDR; # @storage + # == default == # @storage + NIL operation; # list operation : @storage + PAIR; # pair (list operation) @storage + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/car.tz b/tests_python/contracts_009/opcodes/car.tz new file mode 100644 index 0000000000000000000000000000000000000000..8fd03ba5105277a2cf4dfedfe09eaf748b4031c3 --- /dev/null +++ b/tests_python/contracts_009/opcodes/car.tz @@ -0,0 +1,3 @@ +parameter (pair (nat :l) (nat :r)); +storage nat; +code { CAR; CAR ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/cdr.tz b/tests_python/contracts_009/opcodes/cdr.tz new file mode 100644 index 0000000000000000000000000000000000000000..dae260c5be74cdf18a0380f2c2e75f6be0e47152 --- /dev/null +++ b/tests_python/contracts_009/opcodes/cdr.tz @@ -0,0 +1,3 @@ +parameter (pair (nat :l) (nat :r)); +storage nat; +code { CAR; CDR ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/chain_id.tz b/tests_python/contracts_009/opcodes/chain_id.tz new file mode 100644 index 0000000000000000000000000000000000000000..783d13fa0afc22f0b8e9701152e1420635cf7cb8 --- /dev/null +++ b/tests_python/contracts_009/opcodes/chain_id.tz @@ -0,0 +1,3 @@ +parameter unit; +storage unit; +code { CHAIN_ID; DROP; CAR; NIL operation; PAIR } diff --git a/tests_python/contracts_009/opcodes/chain_id_store.tz b/tests_python/contracts_009/opcodes/chain_id_store.tz new file mode 100644 index 0000000000000000000000000000000000000000..11e57fd210c76ca22b4cdf912e366a70eed91669 --- /dev/null +++ b/tests_python/contracts_009/opcodes/chain_id_store.tz @@ -0,0 +1,3 @@ +parameter unit; +storage (option chain_id); +code { DROP; CHAIN_ID; SOME; NIL operation; PAIR } diff --git a/tests_python/contracts_009/opcodes/check_signature.tz b/tests_python/contracts_009/opcodes/check_signature.tz new file mode 100644 index 0000000000000000000000000000000000000000..b5d5b284264864ad8aba341673cdfe3a3652a43d --- /dev/null +++ b/tests_python/contracts_009/opcodes/check_signature.tz @@ -0,0 +1,10 @@ +parameter key; +storage (pair signature string); +code { + DUP; DUP; + DIP{ CDR; DUP; CAR; + DIP{CDR; PACK}}; + CAR; CHECK_SIGNATURE; + IF {} {FAIL} ; + CDR; NIL operation ; PAIR}; + diff --git a/tests_python/contracts_009/opcodes/comb-get.tz b/tests_python/contracts_009/opcodes/comb-get.tz new file mode 100644 index 0000000000000000000000000000000000000000..5493d68f269618de12f63d07f419ef1cdb97f341 --- /dev/null +++ b/tests_python/contracts_009/opcodes/comb-get.tz @@ -0,0 +1,27 @@ +# See also ../macros/carn_and_cdrn.tz for the same test using the +# CAR n and CDR n macros. +parameter (pair nat nat nat unit); +storage unit; +code { + CAR ; + + # Checking the first element + DUP ; CAR ; + PUSH nat 1 ; ASSERT_CMPEQ ; + DUP ; GET 1 ; + PUSH nat 1 ; ASSERT_CMPEQ ; + + # Checking the second element + DUP ; GET 3 ; + PUSH nat 4 ; ASSERT_CMPEQ ; + + # Checking the third element + DUP ; GET 5 ; + PUSH nat 2 ; ASSERT_CMPEQ ; + + # Checking the last (fourth) element + DUP ; GET 6 ; + UNIT ; ASSERT_CMPEQ ; + + DROP ; UNIT ; NIL operation ; PAIR + } diff --git a/tests_python/contracts_009/opcodes/comb-literals.tz b/tests_python/contracts_009/opcodes/comb-literals.tz new file mode 100644 index 0000000000000000000000000000000000000000..2a2b217d78577ca5bcddc18dd28f7eb29bb9553e --- /dev/null +++ b/tests_python/contracts_009/opcodes/comb-literals.tz @@ -0,0 +1,9 @@ +# This pushes a list of combs to test the effect of the normalize script command +parameter unit; +storage unit; +code { + PUSH + (list (pair nat nat nat nat)) + {Pair 0 3 6 9; Pair 1 (Pair 4 (Pair 7 10)); {2; 5; 8; 11}}; + DROP 2; UNIT; NIL operation; PAIR + } diff --git a/tests_python/contracts_009/opcodes/comb-set-2.tz b/tests_python/contracts_009/opcodes/comb-set-2.tz new file mode 100644 index 0000000000000000000000000000000000000000..757acfd380e61bd472ebaa0dddcaefc53cae8e42 --- /dev/null +++ b/tests_python/contracts_009/opcodes/comb-set-2.tz @@ -0,0 +1,10 @@ +# This tests UPDATE on combs. Contrary to comb-set.tz, both the values +# and their types are updated. +parameter (pair nat nat nat unit); +storage (option (pair int nat string bytes)); +code { + CAR ; + PUSH int 2 ; UPDATE 1 ; + PUSH string "toto" ; UPDATE 5 ; + PUSH bytes 0x01 ; UPDATE 6 ; + SOME ; NIL operation ; PAIR ; } diff --git a/tests_python/contracts_009/opcodes/comb-set.tz b/tests_python/contracts_009/opcodes/comb-set.tz new file mode 100644 index 0000000000000000000000000000000000000000..fe407571923ee2fbe1283fadd52942886f3b115c --- /dev/null +++ b/tests_python/contracts_009/opcodes/comb-set.tz @@ -0,0 +1,10 @@ +# This tests UPDATE on combs. See also comb-set-2.tz for tests of +# UPDATE that also change the type of fields. +parameter unit; +storage (pair nat nat nat unit); +code { CDR ; + PUSH nat 2 ; UPDATE 1 ; + PUSH nat 12 ; UPDATE 3 ; + PUSH nat 8 ; UPDATE 5 ; + UNIT ; UPDATE 6 ; + NIL operation ; PAIR ; } diff --git a/tests_python/contracts_009/opcodes/comb.tz b/tests_python/contracts_009/opcodes/comb.tz new file mode 100644 index 0000000000000000000000000000000000000000..6709bde8b8834a72b6f79c46737d0d35657c5089 --- /dev/null +++ b/tests_python/contracts_009/opcodes/comb.tz @@ -0,0 +1,9 @@ +parameter unit; +storage (pair nat nat nat); +code { DROP ; + PUSH nat 3 ; + PUSH nat 2 ; + PUSH nat 1 ; + NIL operation ; + PAIR 4 + } diff --git a/tests_python/contracts_009/opcodes/compare.tz b/tests_python/contracts_009/opcodes/compare.tz new file mode 100644 index 0000000000000000000000000000000000000000..963215fb46cd625a11ee6c1d1c27cbc527a09e18 --- /dev/null +++ b/tests_python/contracts_009/opcodes/compare.tz @@ -0,0 +1,52 @@ +parameter unit; +storage unit; +code { + DROP; + + # bool + PUSH bool True; DUP; COMPARE; ASSERT_EQ; + PUSH bool False; DUP; COMPARE; ASSERT_EQ; + PUSH bool False; PUSH bool True; COMPARE; ASSERT_GT; + PUSH bool True; PUSH bool False; COMPARE; ASSERT_LT; + + # bytes + PUSH bytes 0xAABBCC; DUP; COMPARE; ASSERT_EQ; + PUSH bytes 0x; PUSH bytes 0x; COMPARE; ASSERT_EQ; + PUSH bytes 0x; PUSH bytes 0x01; COMPARE; ASSERT_GT; + PUSH bytes 0x01; PUSH bytes 0x02; COMPARE; ASSERT_GT; + PUSH bytes 0x02; PUSH bytes 0x01; COMPARE; ASSERT_LT; + + # int + PUSH int 1; DUP; COMPARE; ASSERT_EQ; + PUSH int 10; PUSH int 5; COMPARE; ASSERT_LT; + PUSH int -4; PUSH int 1923; COMPARE; ASSERT_GT; + + # nat + PUSH nat 1; DUP; COMPARE; ASSERT_EQ; + PUSH nat 10; PUSH nat 5; COMPARE; ASSERT_LT; + PUSH nat 4; PUSH nat 1923; COMPARE; ASSERT_GT; + + # key_hash + PUSH key_hash "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; DUP; COMPARE; ASSERT_EQ; + PUSH key_hash "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv"; PUSH key_hash "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; COMPARE; ASSERT_LT; + PUSH key_hash "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; PUSH key_hash "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv"; COMPARE; ASSERT_GT; + + # mutez + PUSH mutez 1; DUP; COMPARE; ASSERT_EQ; + PUSH mutez 10; PUSH mutez 5; COMPARE; ASSERT_LT; + PUSH mutez 4; PUSH mutez 1923; COMPARE; ASSERT_GT; + + # string + PUSH string "AABBCC"; DUP; COMPARE; ASSERT_EQ; + PUSH string ""; PUSH string ""; COMPARE; ASSERT_EQ; + PUSH string ""; PUSH string "a"; COMPARE; ASSERT_GT; + PUSH string "a"; PUSH string "b"; COMPARE; ASSERT_GT; + PUSH string "b"; PUSH string "a"; COMPARE; ASSERT_LT; + + # timestamp + PUSH timestamp "2019-09-16T08:38:05Z"; DUP; COMPARE; ASSERT_EQ; + PUSH timestamp "2017-09-16T08:38:04Z"; PUSH timestamp "2019-09-16T08:38:05Z"; COMPARE; ASSERT_GT; + PUSH timestamp "2019-09-16T08:38:05Z"; PUSH timestamp "2019-09-16T08:38:04Z"; COMPARE; ASSERT_LT; + + UNIT; NIL operation; PAIR; + } diff --git a/tests_python/contracts_009/opcodes/compare_big_type.tz b/tests_python/contracts_009/opcodes/compare_big_type.tz new file mode 100644 index 0000000000000000000000000000000000000000..666ad3137777c822a12b5ebaba438d90cb440855 --- /dev/null +++ b/tests_python/contracts_009/opcodes/compare_big_type.tz @@ -0,0 +1,20 @@ +# This contract should cost a lot of gas to typecheck +# because big types are compared in COMPARE +parameter unit; +storage unit; +code { DROP; PUSH nat 0 ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DROP ; UNIT ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/compare_big_type2.tz b/tests_python/contracts_009/opcodes/compare_big_type2.tz new file mode 100644 index 0000000000000000000000000000000000000000..126217d79fdf3075dd6db9c1d6f955f08576e241 --- /dev/null +++ b/tests_python/contracts_009/opcodes/compare_big_type2.tz @@ -0,0 +1,22 @@ +# Like compare_big_type.tz but with an extra line +# DUP ; DUP ; COMPARE ; DROP ; +# so that we can measure how much it costs +parameter unit; +storage unit; +code { DROP; PUSH nat 0 ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DUP ; DUP ; COMPARE ; DROP ; + DROP ; UNIT ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/comparisons.tz b/tests_python/contracts_009/opcodes/comparisons.tz new file mode 100644 index 0000000000000000000000000000000000000000..c603f07339ce7bc6f62bf73c63bf7967ccf79c05 --- /dev/null +++ b/tests_python/contracts_009/opcodes/comparisons.tz @@ -0,0 +1,15 @@ +parameter (list int); +storage (list (list bool)); +code { + CAR; + + NIL (list bool); + DIP {DUP; MAP { EQ; };}; SWAP; CONS; + DIP {DUP; MAP { NEQ; };}; SWAP; CONS; + DIP {DUP; MAP { LE; };}; SWAP; CONS; + DIP {DUP; MAP { LT; };}; SWAP; CONS; + DIP {DUP; MAP { GE; };}; SWAP; CONS; + DIP {MAP { GT; };}; SWAP; CONS; + + NIL operation; PAIR; + } diff --git a/tests_python/contracts_009/opcodes/concat_hello.tz b/tests_python/contracts_009/opcodes/concat_hello.tz new file mode 100644 index 0000000000000000000000000000000000000000..e290b90fb2ad79b77e2011ee43033288d54d4caa --- /dev/null +++ b/tests_python/contracts_009/opcodes/concat_hello.tz @@ -0,0 +1,4 @@ +parameter (list string); +storage (list string); +code{ CAR; + MAP { PUSH @hello string "Hello "; CONCAT }; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/concat_hello_bytes.tz b/tests_python/contracts_009/opcodes/concat_hello_bytes.tz new file mode 100644 index 0000000000000000000000000000000000000000..55f8ab7a216ba24a3dc4e21f6648cfbf0abdea29 --- /dev/null +++ b/tests_python/contracts_009/opcodes/concat_hello_bytes.tz @@ -0,0 +1,4 @@ +parameter (list bytes); +storage (list bytes); +code{ CAR; + MAP { PUSH bytes 0xFF; CONCAT }; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/concat_list.tz b/tests_python/contracts_009/opcodes/concat_list.tz new file mode 100644 index 0000000000000000000000000000000000000000..b570027ff68e6f23b20be8f6869ea12344580710 --- /dev/null +++ b/tests_python/contracts_009/opcodes/concat_list.tz @@ -0,0 +1,5 @@ +parameter (list string); +storage string; +code {CAR; PUSH string ""; SWAP; + ITER {SWAP; DIP{NIL string; SWAP; CONS}; CONS; CONCAT}; + NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/cons.tz b/tests_python/contracts_009/opcodes/cons.tz new file mode 100644 index 0000000000000000000000000000000000000000..5189b47c36b417dda6f3e89f31a4f653970e8fad --- /dev/null +++ b/tests_python/contracts_009/opcodes/cons.tz @@ -0,0 +1,3 @@ +parameter int; +storage (list int); +code { UNPAIR; CONS; NIL operation; PAIR; }; diff --git a/tests_python/contracts_009/opcodes/contains_all.tz b/tests_python/contracts_009/opcodes/contains_all.tz new file mode 100644 index 0000000000000000000000000000000000000000..fe4160f8722733ad86d08acde60fb6b74f682319 --- /dev/null +++ b/tests_python/contracts_009/opcodes/contains_all.tz @@ -0,0 +1,7 @@ +parameter (pair (list string) (list string)); +storage (option bool); +code {CAR; DUP; CAR; DIP{CDR}; EMPTY_SET string; SWAP; + ITER {PAIR; DUP; CAR; DIP{CDR}; PUSH bool True; SWAP; UPDATE}; + PUSH bool True; SWAP; PAIR; SWAP; + ITER {PAIR; DUP; DUP; CAR; DIP{CDAR; DIP{CDDR}; DUP}; MEM; DIP{SWAP}; AND; SWAP; PAIR}; + CDR; SOME; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/contract.tz b/tests_python/contracts_009/opcodes/contract.tz new file mode 100644 index 0000000000000000000000000000000000000000..939337918d1ce883ee782fc92a20b8a9c8247aff --- /dev/null +++ b/tests_python/contracts_009/opcodes/contract.tz @@ -0,0 +1,11 @@ +parameter address; +storage unit; +code { + CAR; + CONTRACT unit; + ASSERT_SOME; + DROP; + UNIT; + NIL operation; + PAIR + }; diff --git a/tests_python/contracts_009/opcodes/create_contract.tz b/tests_python/contracts_009/opcodes/create_contract.tz new file mode 100644 index 0000000000000000000000000000000000000000..d3fb8dc617a87ea8fd9aa388bafc7f8f651a7539 --- /dev/null +++ b/tests_python/contracts_009/opcodes/create_contract.tz @@ -0,0 +1,14 @@ +parameter unit; +storage (option address); +code { DROP; + UNIT; # starting storage for contract + AMOUNT; # Push the starting balance + NONE key_hash; # No delegate + CREATE_CONTRACT # Create the contract + { parameter unit ; + storage unit ; + code + { CDR; + NIL operation; + PAIR; } }; + DIP {SOME;NIL operation};CONS ; PAIR} # Ending calling convention stuff diff --git a/tests_python/contracts_009/opcodes/create_contract_rootname.tz b/tests_python/contracts_009/opcodes/create_contract_rootname.tz new file mode 100644 index 0000000000000000000000000000000000000000..b85b4cf8bb414ff256a62fadd41d5e50755d5d9e --- /dev/null +++ b/tests_python/contracts_009/opcodes/create_contract_rootname.tz @@ -0,0 +1,15 @@ +# this contract creates a contract +parameter unit; +storage (option address); +code { DROP; + UNIT; # starting storage for contract + AMOUNT; # Push the starting balance + NONE key_hash; # No delegate + CREATE_CONTRACT # Create the contract + { parameter %root unit ; + storage unit ; + code + { CDR; + NIL operation; + PAIR; } }; + DIP {SOME;NIL operation}; CONS ; PAIR} # Ending calling convention stuff diff --git a/tests_python/contracts_009/opcodes/create_contract_rootname_alt.tz b/tests_python/contracts_009/opcodes/create_contract_rootname_alt.tz new file mode 100644 index 0000000000000000000000000000000000000000..226a9abba298786ed2d420eabccc91e935120834 --- /dev/null +++ b/tests_python/contracts_009/opcodes/create_contract_rootname_alt.tz @@ -0,0 +1,14 @@ +parameter unit; +storage (option address); +code { DROP; + UNIT; # starting storage for contract + AMOUNT; # Push the starting balance + NONE key_hash; # No delegate + CREATE_CONTRACT # Create the contract + { parameter (unit %root) ; + storage unit ; + code + { CDR; + NIL operation; + PAIR; } }; + DIP {SOME;NIL operation}; CONS ; PAIR} # Ending calling convention stuff diff --git a/tests_python/contracts_009/opcodes/diff_timestamps.tz b/tests_python/contracts_009/opcodes/diff_timestamps.tz new file mode 100644 index 0000000000000000000000000000000000000000..f1991a37a5d276c86bfd13fb7cb4c14fc0892e09 --- /dev/null +++ b/tests_python/contracts_009/opcodes/diff_timestamps.tz @@ -0,0 +1,3 @@ +parameter (pair timestamp timestamp); +storage int; +code { CAR; DUP; CAR; DIP{CDR}; SUB; NIL operation; PAIR } diff --git a/tests_python/contracts_009/opcodes/dig_eq.tz b/tests_python/contracts_009/opcodes/dig_eq.tz new file mode 100644 index 0000000000000000000000000000000000000000..aaafc4271faec9dcb62044abd1fd7909ba30f752 --- /dev/null +++ b/tests_python/contracts_009/opcodes/dig_eq.tz @@ -0,0 +1,14 @@ +parameter (pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat); +storage unit; +# this contract receives a 17-tuple, unpairs it, reverses the order, reverses it again, and pairs it and verifies that the result is the same as the original tuple. +code { CAR; + DUP; + + UNPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAIR; + DIG 0; DIG 1; DIG 2; DIG 3; DIG 4; DIG 5; DIG 6; DIG 7; DIG 8; DIG 9; DIG 10; DIG 11; DIG 12; DIG 13; DIG 14; DIG 15; DIG 16; + # PUSH nat 1; ADD; + DIG 0; DIG 1; DIG 2; DIG 3; DIG 4; DIG 5; DIG 6; DIG 7; DIG 8; DIG 9; DIG 10; DIG 11; DIG 12; DIG 13; DIG 14; DIG 15; DIG 16; + PAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAIR; + ASSERT_CMPEQ; + + UNIT; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/dign.tz b/tests_python/contracts_009/opcodes/dign.tz new file mode 100644 index 0000000000000000000000000000000000000000..ec8a339dd48c3c7318c72dfbce9b562839df48e1 --- /dev/null +++ b/tests_python/contracts_009/opcodes/dign.tz @@ -0,0 +1,3 @@ +parameter (pair (pair (pair (pair nat nat) nat) nat) nat); +storage nat; +code {CAR; UNPAIR ; UNPAIR ; UNPAIR ; UNPAIR ; DIG 4 ; DIP { DROP ; DROP ; DROP ; DROP } ; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/dip.tz b/tests_python/contracts_009/opcodes/dip.tz new file mode 100644 index 0000000000000000000000000000000000000000..f0c32a838747fe221cbb5570ae32383f6c8fb5d0 --- /dev/null +++ b/tests_python/contracts_009/opcodes/dip.tz @@ -0,0 +1,8 @@ +parameter (pair nat nat); +storage (pair nat nat); +code{ + CAR; UNPAIR; + DUP; DIP { ADD }; + PAIR; + NIL operation; + PAIR}; diff --git a/tests_python/contracts_009/opcodes/dipn.tz b/tests_python/contracts_009/opcodes/dipn.tz new file mode 100644 index 0000000000000000000000000000000000000000..55d088e5518f3bff8321669c94bbd1689a00c796 --- /dev/null +++ b/tests_python/contracts_009/opcodes/dipn.tz @@ -0,0 +1,3 @@ +parameter (pair (pair (pair (pair nat nat) nat) nat) nat); +storage nat; +code {CAR; UNPAIR ; UNPAIR ; UNPAIR ; UNPAIR ; DIP 5 {PUSH nat 6} ; DROP ; DROP ; DROP ; DROP ; DROP ; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/dropn.tz b/tests_python/contracts_009/opcodes/dropn.tz new file mode 100644 index 0000000000000000000000000000000000000000..4b5379b3a3b3ee3f12d1ff9110d58b2683aa953e --- /dev/null +++ b/tests_python/contracts_009/opcodes/dropn.tz @@ -0,0 +1,3 @@ +parameter (pair (pair (pair (pair nat nat) nat) nat) nat); +storage nat; +code {CAR; UNPAIR ; UNPAIR ; UNPAIR ; UNPAIR ; DROP 4 ; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/dugn.tz b/tests_python/contracts_009/opcodes/dugn.tz new file mode 100644 index 0000000000000000000000000000000000000000..521c052f1fcd593c2707ae9698df9992cab55367 --- /dev/null +++ b/tests_python/contracts_009/opcodes/dugn.tz @@ -0,0 +1,3 @@ +parameter (pair (pair (pair (pair nat nat) nat) nat) nat); +storage nat; +code {CAR; UNPAIR ; UNPAIR ; UNPAIR ; UNPAIR ; DUG 4 ; DROP ; DROP ; DROP ; DROP ; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/dup-n.tz b/tests_python/contracts_009/opcodes/dup-n.tz new file mode 100644 index 0000000000000000000000000000000000000000..7e530c0971d02a6a121862a1a36279da33e92bde --- /dev/null +++ b/tests_python/contracts_009/opcodes/dup-n.tz @@ -0,0 +1,18 @@ +parameter unit; +storage unit; +code + { + DROP ; + PUSH nat 5 ; + PUSH nat 4 ; + PUSH nat 3 ; + PUSH nat 2 ; + PUSH nat 1 ; + DUP 1 ; PUSH nat 1 ; ASSERT_CMPEQ ; + DUP 2 ; PUSH nat 2 ; ASSERT_CMPEQ ; + DUP 3 ; PUSH nat 3 ; ASSERT_CMPEQ ; + DUP 4 ; PUSH nat 4 ; ASSERT_CMPEQ ; + DUP 5 ; PUSH nat 5 ; ASSERT_CMPEQ ; + DROP 5 ; + UNIT ; NIL operation ; PAIR ; + }; diff --git a/tests_python/contracts_009/opcodes/ediv.tz b/tests_python/contracts_009/opcodes/ediv.tz new file mode 100644 index 0000000000000000000000000000000000000000..a1fc89992a023a3988c151bcd7d43fa1e1ba32f4 --- /dev/null +++ b/tests_python/contracts_009/opcodes/ediv.tz @@ -0,0 +1,13 @@ +parameter (pair int int); +storage (pair (option (pair int nat)) (option (pair int nat)) (option (pair int nat)) (option (pair nat nat))); +code { CAR; + # :: nat : nat : 'S -> option (pair nat nat) : 'S + DUP; UNPAIR; ABS; DIP { ABS; }; EDIV; SWAP; + # :: nat : int : 'S -> option (pair int nat) : 'S + DUP; UNPAIR; ABS; EDIV; SWAP; + # :: int : nat : 'S -> option (pair int nat) : 'S + DUP; UNPAIR; DIP { ABS; }; EDIV; SWAP; + # :: int : int : 'S -> option (pair int nat) : 'S + UNPAIR; EDIV; + PAPAPAIR; + NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/ediv_mutez.tz b/tests_python/contracts_009/opcodes/ediv_mutez.tz new file mode 100644 index 0000000000000000000000000000000000000000..2df73dd4a0e3b6cdd3a2451b82f21c7751ece275 --- /dev/null +++ b/tests_python/contracts_009/opcodes/ediv_mutez.tz @@ -0,0 +1,12 @@ +parameter (pair mutez (or mutez nat)); +storage (or (option (pair nat mutez)) (option (pair mutez mutez))); +code { CAR; + UNPAIR; + SWAP; + IF_LEFT { + SWAP; EDIV; LEFT (option (pair mutez mutez)); + } + { + SWAP; EDIV; RIGHT (option (pair nat mutez)); + }; + NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/empty_map.tz b/tests_python/contracts_009/opcodes/empty_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..9023fe847b3f9a225b5e2e122315e1cbaa8d8365 --- /dev/null +++ b/tests_python/contracts_009/opcodes/empty_map.tz @@ -0,0 +1,6 @@ +storage (map string string); +parameter unit; +code {DROP; + EMPTY_MAP string string; + PUSH string "world"; SOME; PUSH string "hello"; UPDATE; + NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/exec_concat.tz b/tests_python/contracts_009/opcodes/exec_concat.tz new file mode 100644 index 0000000000000000000000000000000000000000..0265f1557f0efb7e9a3b93a649fe3f61c27a50e4 --- /dev/null +++ b/tests_python/contracts_009/opcodes/exec_concat.tz @@ -0,0 +1,7 @@ +parameter string; +storage string; +code {CAR; + LAMBDA string string + {PUSH string "_abc"; NIL string ; + SWAP ; CONS ; SWAP ; CONS ; CONCAT}; + SWAP; EXEC; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/first.tz b/tests_python/contracts_009/opcodes/first.tz new file mode 100644 index 0000000000000000000000000000000000000000..6e47b4c008e8be9db842d8739d1a61357576d699 --- /dev/null +++ b/tests_python/contracts_009/opcodes/first.tz @@ -0,0 +1,3 @@ +parameter (list nat); +storage nat; +code{CAR; IF_CONS {DIP{DROP}} {FAIL}; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/get_and_update_big_map.tz b/tests_python/contracts_009/opcodes/get_and_update_big_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..3b39c9a6f7332a4993cd35c7059d410995e427ec --- /dev/null +++ b/tests_python/contracts_009/opcodes/get_and_update_big_map.tz @@ -0,0 +1,9 @@ +parameter string; +storage (pair (option nat) (big_map string nat)); +code { + UNPAPAIR; + GET_AND_UPDATE; + PAIR; + NIL operation; + PAIR + } diff --git a/tests_python/contracts_009/opcodes/get_and_update_map.tz b/tests_python/contracts_009/opcodes/get_and_update_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..b67f08ce7746e3ae0e707277e40c907882a685a9 --- /dev/null +++ b/tests_python/contracts_009/opcodes/get_and_update_map.tz @@ -0,0 +1,9 @@ +parameter string; +storage (pair (option nat) (map string nat)); +code { + UNPAPAIR; + GET_AND_UPDATE; + PAIR; + NIL operation; + PAIR + } diff --git a/tests_python/contracts_009/opcodes/get_big_map_value.tz b/tests_python/contracts_009/opcodes/get_big_map_value.tz new file mode 100644 index 0000000000000000000000000000000000000000..4ca52343d45afabdfa0b19671d45bbf74b642de2 --- /dev/null +++ b/tests_python/contracts_009/opcodes/get_big_map_value.tz @@ -0,0 +1,6 @@ +parameter string; +storage (pair (big_map string string) (option string)); +# retrieves the values stored in the big_map on the left side of the +# pair at the key denoted by the parameter and puts it in the right +# hand side of the storage +code {DUP; CAR; DIP{CDAR; DUP}; GET; SWAP; PAIR; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/get_map_value.tz b/tests_python/contracts_009/opcodes/get_map_value.tz new file mode 100644 index 0000000000000000000000000000000000000000..f46639649a34ccdbe0028f852dbba0a2306260c3 --- /dev/null +++ b/tests_python/contracts_009/opcodes/get_map_value.tz @@ -0,0 +1,3 @@ +parameter string; +storage (pair (option string) (map string string)); +code {DUP; CAR; DIP{CDDR; DUP}; GET; PAIR; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/hash_consistency_checker.tz b/tests_python/contracts_009/opcodes/hash_consistency_checker.tz new file mode 100644 index 0000000000000000000000000000000000000000..fb98a39da496ab314d8b27b0c988d0812d83b3ca --- /dev/null +++ b/tests_python/contracts_009/opcodes/hash_consistency_checker.tz @@ -0,0 +1,3 @@ +parameter (pair mutez (pair timestamp int)) ; +storage bytes ; +code { CAR ; PACK ; BLAKE2B ; NIL operation ; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/hash_key.tz b/tests_python/contracts_009/opcodes/hash_key.tz new file mode 100644 index 0000000000000000000000000000000000000000..6c7f78b4aaf6f843558723fa51bff121d4d00cf3 --- /dev/null +++ b/tests_python/contracts_009/opcodes/hash_key.tz @@ -0,0 +1,3 @@ +parameter key; +storage (option key_hash); +code {CAR; HASH_KEY; SOME ;NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/hash_string.tz b/tests_python/contracts_009/opcodes/hash_string.tz new file mode 100644 index 0000000000000000000000000000000000000000..b0b8ddea6403c054f83f3899118077712c7d0e13 --- /dev/null +++ b/tests_python/contracts_009/opcodes/hash_string.tz @@ -0,0 +1,3 @@ +parameter string; +storage bytes; +code {CAR; PACK ; BLAKE2B; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/if.tz b/tests_python/contracts_009/opcodes/if.tz new file mode 100644 index 0000000000000000000000000000000000000000..4bc0e353daebbea531688c768b19c1040da69b85 --- /dev/null +++ b/tests_python/contracts_009/opcodes/if.tz @@ -0,0 +1,3 @@ +parameter bool; +storage (option bool); +code {CAR; IF {PUSH bool True} {PUSH bool False}; SOME; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/if_some.tz b/tests_python/contracts_009/opcodes/if_some.tz new file mode 100644 index 0000000000000000000000000000000000000000..5c3138b2272b188c444455b12de75f3ce5025918 --- /dev/null +++ b/tests_python/contracts_009/opcodes/if_some.tz @@ -0,0 +1,3 @@ +parameter (option string); +storage string; +code { CAR; IF_SOME {} {PUSH string ""}; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/int.tz b/tests_python/contracts_009/opcodes/int.tz new file mode 100644 index 0000000000000000000000000000000000000000..3f199881392ae45abe9ae7332c5b63ba6b735b36 --- /dev/null +++ b/tests_python/contracts_009/opcodes/int.tz @@ -0,0 +1,5 @@ +parameter nat; +storage (option int); +# this contract takes a natural number as parameter, converts it to an +# integer and stores it. +code { CAR; INT; SOME; NIL operation; PAIR }; diff --git a/tests_python/contracts_009/opcodes/keccak.tz b/tests_python/contracts_009/opcodes/keccak.tz new file mode 100644 index 0000000000000000000000000000000000000000..e96256100999075084931c4334798fbdcac54525 --- /dev/null +++ b/tests_python/contracts_009/opcodes/keccak.tz @@ -0,0 +1,8 @@ +storage (option bytes); +parameter bytes; +code + { + CAR; + KECCAK; SOME; + NIL operation; PAIR + } diff --git a/tests_python/contracts_009/opcodes/left_right.tz b/tests_python/contracts_009/opcodes/left_right.tz new file mode 100644 index 0000000000000000000000000000000000000000..d5650c03422ecd43c39e9768b96383d6a17ad306 --- /dev/null +++ b/tests_python/contracts_009/opcodes/left_right.tz @@ -0,0 +1,3 @@ +parameter (or bool string); +storage (or string bool); +code {CAR; IF_LEFT {RIGHT string} {LEFT bool}; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/level.tz b/tests_python/contracts_009/opcodes/level.tz new file mode 100644 index 0000000000000000000000000000000000000000..7e3adb9d05f415dac16763c8dfe40c72c8f37501 --- /dev/null +++ b/tests_python/contracts_009/opcodes/level.tz @@ -0,0 +1,3 @@ +parameter unit; +storage nat; +code {DROP; LEVEL; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/list_concat.tz b/tests_python/contracts_009/opcodes/list_concat.tz new file mode 100644 index 0000000000000000000000000000000000000000..d7bfb7d134eaa57ec797c6a8b0b6b1333cf5ec77 --- /dev/null +++ b/tests_python/contracts_009/opcodes/list_concat.tz @@ -0,0 +1,3 @@ +parameter (list string); +storage string; +code { UNPAIR ; SWAP ; CONS ; CONCAT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/list_concat_bytes.tz b/tests_python/contracts_009/opcodes/list_concat_bytes.tz new file mode 100644 index 0000000000000000000000000000000000000000..0fc8e162066954a2b57ac13d074694e9b8d020b8 --- /dev/null +++ b/tests_python/contracts_009/opcodes/list_concat_bytes.tz @@ -0,0 +1,3 @@ +parameter (list bytes); +storage bytes; +code { UNPAIR ; SWAP ; CONS ; CONCAT; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/list_id.tz b/tests_python/contracts_009/opcodes/list_id.tz new file mode 100644 index 0000000000000000000000000000000000000000..6cd3693a1e14f5572585228bcfebe8e10331232d --- /dev/null +++ b/tests_python/contracts_009/opcodes/list_id.tz @@ -0,0 +1,3 @@ +parameter (list string); +storage (list string); +code {CAR; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/list_id_map.tz b/tests_python/contracts_009/opcodes/list_id_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..38b4493e8e0fd5d0797eb949b61b906a80fc4a51 --- /dev/null +++ b/tests_python/contracts_009/opcodes/list_id_map.tz @@ -0,0 +1,3 @@ +parameter (list string); +storage (list string); +code {CAR; MAP {}; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/list_iter.tz b/tests_python/contracts_009/opcodes/list_iter.tz new file mode 100644 index 0000000000000000000000000000000000000000..df904d882234fa087193b24099ee2b6f4aa53576 --- /dev/null +++ b/tests_python/contracts_009/opcodes/list_iter.tz @@ -0,0 +1,5 @@ +parameter (list int); +storage int; +code { CAR; PUSH int 1; SWAP; + ITER { MUL }; + NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/list_map_block.tz b/tests_python/contracts_009/opcodes/list_map_block.tz new file mode 100644 index 0000000000000000000000000000000000000000..b5202dd9b6fb881f2af60d71f47edaa4355f672b --- /dev/null +++ b/tests_python/contracts_009/opcodes/list_map_block.tz @@ -0,0 +1,5 @@ +parameter (list int); +storage (list int); +code { CAR; PUSH int 0; SWAP; + MAP { DIP{DUP}; ADD; DIP{PUSH int 1; ADD}}; + NIL operation; PAIR; DIP{DROP}} diff --git a/tests_python/contracts_009/opcodes/list_size.tz b/tests_python/contracts_009/opcodes/list_size.tz new file mode 100644 index 0000000000000000000000000000000000000000..6ced12799187fa76705a31e3f07bb9dc7c493d6b --- /dev/null +++ b/tests_python/contracts_009/opcodes/list_size.tz @@ -0,0 +1,3 @@ +parameter (list int); +storage nat; +code {CAR; SIZE; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/loop_left.tz b/tests_python/contracts_009/opcodes/loop_left.tz new file mode 100644 index 0000000000000000000000000000000000000000..64bcc76c89cc336bb75095632f390525ccc6cf4d --- /dev/null +++ b/tests_python/contracts_009/opcodes/loop_left.tz @@ -0,0 +1,7 @@ +parameter (list string); +storage (list string); +code { CAR; NIL string; SWAP; PAIR; LEFT (list string); + LOOP_LEFT { DUP; CAR; DIP{CDR}; + IF_CONS { SWAP; DIP{CONS}; PAIR; LEFT (list string) } + { RIGHT (pair (list string) (list string)) }; }; + NIL operation; PAIR } diff --git a/tests_python/contracts_009/opcodes/map_car.tz b/tests_python/contracts_009/opcodes/map_car.tz new file mode 100644 index 0000000000000000000000000000000000000000..b763590ece2cf74fe3f1f18c29c9da154b00aa5f --- /dev/null +++ b/tests_python/contracts_009/opcodes/map_car.tz @@ -0,0 +1,5 @@ +parameter bool; +storage (pair (bool %b) (nat %n)); +code { DUP; CAR; DIP{CDR}; SWAP; + MAP_CAR @new_storage %b { AND }; + NIL operation; PAIR }; diff --git a/tests_python/contracts_009/opcodes/map_id.tz b/tests_python/contracts_009/opcodes/map_id.tz new file mode 100644 index 0000000000000000000000000000000000000000..ff0a3bbbf21321a2634edca52229ca753fc8925c --- /dev/null +++ b/tests_python/contracts_009/opcodes/map_id.tz @@ -0,0 +1,3 @@ +parameter (map nat nat); +storage (map nat nat); +code { CAR ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/map_iter.tz b/tests_python/contracts_009/opcodes/map_iter.tz new file mode 100644 index 0000000000000000000000000000000000000000..3ab5c35c73b87885d00182c2820b0c9932706fb1 --- /dev/null +++ b/tests_python/contracts_009/opcodes/map_iter.tz @@ -0,0 +1,7 @@ +parameter (map (int :k) (int :e)); +storage (pair (int :k) (int :e)); +code { CAR; PUSH @acc_e (int :e) 0; PUSH @acc_k (int :k) 0; PAIR % %r; SWAP; + ITER + { DIP {DUP; CAR; DIP{CDR}}; DUP; # Last instr + DIP{CAR; ADD}; SWAP; DIP{CDR; ADD}; PAIR % %r }; + NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/map_map.tz b/tests_python/contracts_009/opcodes/map_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..4acbd63c32c4d5409e051c6c1eed5703c19c9a10 --- /dev/null +++ b/tests_python/contracts_009/opcodes/map_map.tz @@ -0,0 +1,8 @@ +parameter nat; +storage (map string nat); +# this contract adds the value passed by parameter to each entry in +# the stored map. +code { UNPAIR; SWAP; + MAP { CDR; DIP {DUP}; ADD; }; + DIP { DROP; }; + NIL operation; PAIR; } diff --git a/tests_python/contracts_009/opcodes/map_map_sideeffect.tz b/tests_python/contracts_009/opcodes/map_map_sideeffect.tz new file mode 100644 index 0000000000000000000000000000000000000000..960b02a553ceb8b4d42a2631829df3725c538def --- /dev/null +++ b/tests_python/contracts_009/opcodes/map_map_sideeffect.tz @@ -0,0 +1,12 @@ +parameter nat; +storage (pair (map string nat) nat); +# this contract adds the value passed by parameter to each entry in +# the stored map, and it sets the second component of the pair to the +# sum of the map's elements +code { UNPAIR; SWAP; CAR; + DIP 2 { PUSH @sum nat 0; }; + MAP { CDR; DIP {DUP}; ADD; + DUP; DUG 2; DIP 2 { ADD @sum }; + }; + DIP { DROP; }; PAIR; + NIL operation; PAIR; } diff --git a/tests_python/contracts_009/opcodes/map_mem_nat.tz b/tests_python/contracts_009/opcodes/map_mem_nat.tz new file mode 100644 index 0000000000000000000000000000000000000000..0c245d7e0a652d8430d71d47a1511e6a0d9c874f --- /dev/null +++ b/tests_python/contracts_009/opcodes/map_mem_nat.tz @@ -0,0 +1,7 @@ +parameter nat; +storage (pair (map nat nat) (option bool)) ; +# stores (map, Some flag) where flag = parameter is a member of +# the map in first component of storage +code { UNPAIR; + DIP { CAR; DUP }; + MEM; SOME; SWAP; PAIR; NIL operation; PAIR;} diff --git a/tests_python/contracts_009/opcodes/map_mem_string.tz b/tests_python/contracts_009/opcodes/map_mem_string.tz new file mode 100644 index 0000000000000000000000000000000000000000..3fa5cd5b579f534b9df0b33d5d46d525b56fbbe8 --- /dev/null +++ b/tests_python/contracts_009/opcodes/map_mem_string.tz @@ -0,0 +1,7 @@ +parameter string; +storage (pair (map string nat) (option bool)) ; +# stores (map, Some flag) where flag = parameter is a member of +# the map in first component of storage +code { UNPAIR; + DIP { CAR; DUP }; + MEM; SOME; SWAP; PAIR; NIL operation; PAIR;} diff --git a/tests_python/contracts_009/opcodes/map_size.tz b/tests_python/contracts_009/opcodes/map_size.tz new file mode 100644 index 0000000000000000000000000000000000000000..4bd6417e6d79b25cf4cb835162215fa2a882f2b9 --- /dev/null +++ b/tests_python/contracts_009/opcodes/map_size.tz @@ -0,0 +1,3 @@ +parameter (map string nat); +storage nat; +code {CAR; SIZE; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/merge_comparable_pairs.tz b/tests_python/contracts_009/opcodes/merge_comparable_pairs.tz new file mode 100644 index 0000000000000000000000000000000000000000..14fcc73411c76d7f2719969be63aca805b9cb284 --- /dev/null +++ b/tests_python/contracts_009/opcodes/merge_comparable_pairs.tz @@ -0,0 +1,14 @@ +# tests that merging comparable pair types works +parameter (set (pair (nat %n) (pair %p (string %s) (int %i)))); +storage nat; +code {UNPAIR; + SWAP; + PUSH nat 3; + COMPARE; + GT; + IF {} + {DROP; + EMPTY_SET (pair nat (pair string int));}; + SIZE; + NIL operation; + PAIR;} diff --git a/tests_python/contracts_009/opcodes/mul.tz b/tests_python/contracts_009/opcodes/mul.tz new file mode 100644 index 0000000000000000000000000000000000000000..8432394b526d75ee295a4c79d134cc85525cb2ad --- /dev/null +++ b/tests_python/contracts_009/opcodes/mul.tz @@ -0,0 +1,48 @@ +parameter unit ; +storage unit ; +code { CAR ; + DROP ; + # tez-nat, no overflow + PUSH nat 7987 ; + PUSH mutez 10 ; + MUL ; + PUSH mutez 79870 ; + COMPARE ; + ASSERT_EQ ; + # nat-tez, no overflow + PUSH mutez 10 ; + PUSH nat 7987 ; + MUL ; + PUSH mutez 79870 ; + COMPARE ; + ASSERT_EQ ; + # int-int, no overflow + PUSH int 10 ; + PUSH int -7987 ; + MUL ; + PUSH int -79870 ; + COMPARE ; + ASSERT_EQ ; + # int-nat, no overflow + PUSH nat 10 ; + PUSH int -7987 ; + MUL ; + PUSH int -79870 ; + COMPARE ; + ASSERT_EQ ; + # nat-int, no overflow + PUSH int -10 ; + PUSH nat 7987 ; + MUL ; + PUSH int -79870 ; + COMPARE ; + ASSERT_EQ ; + # nat-nat, no overflow + PUSH nat 10 ; + PUSH nat 7987 ; + MUL ; + PUSH nat 79870 ; + COMPARE ; + ASSERT_EQ ; + + UNIT ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/mul_bls12_381_fr.tz b/tests_python/contracts_009/opcodes/mul_bls12_381_fr.tz new file mode 100644 index 0000000000000000000000000000000000000000..dd201863b0344e31eb92392aa283a0fba5ccf6eb --- /dev/null +++ b/tests_python/contracts_009/opcodes/mul_bls12_381_fr.tz @@ -0,0 +1,3 @@ +parameter (pair bls12_381_fr bls12_381_fr); +storage (option (bls12_381_fr)); +code {CAR; UNPAIR; MUL; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/mul_bls12_381_g1.tz b/tests_python/contracts_009/opcodes/mul_bls12_381_g1.tz new file mode 100644 index 0000000000000000000000000000000000000000..af3f376501da1960d27e8e8180c35d4c942a4be9 --- /dev/null +++ b/tests_python/contracts_009/opcodes/mul_bls12_381_g1.tz @@ -0,0 +1,3 @@ +parameter (pair bls12_381_g1 bls12_381_fr); +storage (option (bls12_381_g1)); +code {CAR; UNPAIR; MUL; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/mul_bls12_381_g2.tz b/tests_python/contracts_009/opcodes/mul_bls12_381_g2.tz new file mode 100644 index 0000000000000000000000000000000000000000..1875e8e3dac87488732502c20a361f8a6eee0772 --- /dev/null +++ b/tests_python/contracts_009/opcodes/mul_bls12_381_g2.tz @@ -0,0 +1,3 @@ +parameter (pair bls12_381_g2 bls12_381_fr); +storage (option (bls12_381_g2)); +code {CAR; UNPAIR; MUL; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/mul_overflow.tz b/tests_python/contracts_009/opcodes/mul_overflow.tz new file mode 100644 index 0000000000000000000000000000000000000000..5d2b3a3dcff20b81817c52bd99a8738c12120f3f --- /dev/null +++ b/tests_python/contracts_009/opcodes/mul_overflow.tz @@ -0,0 +1,18 @@ +parameter (or unit unit) ; +storage unit ; +code { CAR ; + IF_LEFT + { + PUSH nat 922337203685477580700 ; + PUSH mutez 10 ; + MUL ; # FAILURE + DROP + } + { + PUSH mutez 10 ; + PUSH nat 922337203685477580700 ; + MUL ; # FAILURE + DROP + } ; + + NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/munch.tz b/tests_python/contracts_009/opcodes/munch.tz new file mode 100644 index 0000000000000000000000000000000000000000..7efe43ca092d685b1e0c27b6ff4682479309055c --- /dev/null +++ b/tests_python/contracts_009/opcodes/munch.tz @@ -0,0 +1,14 @@ +# A contract that accepts bytes in a default entry point and does nothing. +# Useful for testing transfers of arbitrary sizes. +parameter (or (bytes %bytes) + (or (lambda %lambda unit unit) + (or (nat %nat) + (list %list_nat nat)))); +storage unit; +code + { + CDR; # @storage + # == default == # @storage + NIL operation; # list operation : @storage + PAIR; # pair (list operation) @storage + }; diff --git a/tests_python/contracts_009/opcodes/mutez_to_bls12_381_fr.tz b/tests_python/contracts_009/opcodes/mutez_to_bls12_381_fr.tz new file mode 100644 index 0000000000000000000000000000000000000000..fefc038474da3f39fb9c7f58e005eaeda6f1aede --- /dev/null +++ b/tests_python/contracts_009/opcodes/mutez_to_bls12_381_fr.tz @@ -0,0 +1,14 @@ +parameter mutez; +storage bls12_381_fr; +code { + CAR; + PUSH mutez 1; + SWAP; + EDIV; + ASSERT_SOME; + CAR; + PUSH bls12_381_fr 1; + MUL; + NIL operation; + PAIR; + }; \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/neg.tz b/tests_python/contracts_009/opcodes/neg.tz new file mode 100644 index 0000000000000000000000000000000000000000..9cedf765f1b2ef0c79a102b505037a9cb0c591b7 --- /dev/null +++ b/tests_python/contracts_009/opcodes/neg.tz @@ -0,0 +1,8 @@ +parameter (or int nat); +storage int; +code { + CAR; + IF_LEFT {NEG} {NEG}; + NIL operation; + PAIR + } diff --git a/tests_python/contracts_009/opcodes/neg_bls12_381_fr.tz b/tests_python/contracts_009/opcodes/neg_bls12_381_fr.tz new file mode 100644 index 0000000000000000000000000000000000000000..cd9b0a945cc5161d2a2eb423bae54a9df9dc2047 --- /dev/null +++ b/tests_python/contracts_009/opcodes/neg_bls12_381_fr.tz @@ -0,0 +1,3 @@ +parameter bls12_381_fr; +storage (option (bls12_381_fr)); +code {CAR; NEG; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/neg_bls12_381_g1.tz b/tests_python/contracts_009/opcodes/neg_bls12_381_g1.tz new file mode 100644 index 0000000000000000000000000000000000000000..60806deada202b7aad016a5c57f482f2b0645f9b --- /dev/null +++ b/tests_python/contracts_009/opcodes/neg_bls12_381_g1.tz @@ -0,0 +1,3 @@ +parameter bls12_381_g1; +storage (option (bls12_381_g1)); +code {CAR; NEG; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/neg_bls12_381_g2.tz b/tests_python/contracts_009/opcodes/neg_bls12_381_g2.tz new file mode 100644 index 0000000000000000000000000000000000000000..59305254625839f82b76481a7745f91a5a1726d7 --- /dev/null +++ b/tests_python/contracts_009/opcodes/neg_bls12_381_g2.tz @@ -0,0 +1,3 @@ +parameter bls12_381_g2; +storage (option (bls12_381_g2)); +code {CAR; NEG; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/none.tz b/tests_python/contracts_009/opcodes/none.tz new file mode 100644 index 0000000000000000000000000000000000000000..473a288b492662a3c80c9ff127a9a31bfb95a760 --- /dev/null +++ b/tests_python/contracts_009/opcodes/none.tz @@ -0,0 +1,3 @@ +parameter unit; +storage (option nat); +code { DROP; NONE nat; NIL operation; PAIR; }; diff --git a/tests_python/contracts_009/opcodes/noop.tz b/tests_python/contracts_009/opcodes/noop.tz new file mode 100644 index 0000000000000000000000000000000000000000..bd19da15cf4998ed3e4675778029d02713257599 --- /dev/null +++ b/tests_python/contracts_009/opcodes/noop.tz @@ -0,0 +1,3 @@ +parameter unit; +storage unit; +code {CDR; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/not.tz b/tests_python/contracts_009/opcodes/not.tz new file mode 100644 index 0000000000000000000000000000000000000000..f89394072d2aabea9aadfa4d890afa71f5e1e9c7 --- /dev/null +++ b/tests_python/contracts_009/opcodes/not.tz @@ -0,0 +1,3 @@ +parameter bool; +storage (option bool); +code {CAR; NOT; SOME; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/not_binary.tz b/tests_python/contracts_009/opcodes/not_binary.tz new file mode 100644 index 0000000000000000000000000000000000000000..c1e0f97979d73983ff363a12f66ff0c1df94aa22 --- /dev/null +++ b/tests_python/contracts_009/opcodes/not_binary.tz @@ -0,0 +1,12 @@ +parameter (or int nat); +storage (option int); +code { CAR; + IF_LEFT + { + NOT; + } + { + NOT; + } ; + SOME; NIL operation ; PAIR + } diff --git a/tests_python/contracts_009/opcodes/or.tz b/tests_python/contracts_009/opcodes/or.tz new file mode 100644 index 0000000000000000000000000000000000000000..89d533c4483e31bd3750438e67ddd078cc98004e --- /dev/null +++ b/tests_python/contracts_009/opcodes/or.tz @@ -0,0 +1,3 @@ +parameter (pair bool bool); +storage (option bool); +code {CAR; DUP; CAR; SWAP; CDR; OR; SOME; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/or_binary.tz b/tests_python/contracts_009/opcodes/or_binary.tz new file mode 100644 index 0000000000000000000000000000000000000000..a31f109827efa3a00b776eb1fa473e1a6800bbe9 --- /dev/null +++ b/tests_python/contracts_009/opcodes/or_binary.tz @@ -0,0 +1,9 @@ +parameter (pair nat nat); +storage (option nat); +# This contract takes a pair of natural numbers as argument and +# stores the result of their binary OR. +code { CAR; + UNPAIR; + OR; + SOME; NIL operation; PAIR + } diff --git a/tests_python/contracts_009/opcodes/originate_big_map.tz b/tests_python/contracts_009/opcodes/originate_big_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..97d7db669fe8f70565ba6370738ebffda0ae1102 --- /dev/null +++ b/tests_python/contracts_009/opcodes/originate_big_map.tz @@ -0,0 +1,3 @@ +parameter (big_map int int); +storage (big_map int int); +code { CAR; NIL operation; PAIR } diff --git a/tests_python/contracts_009/opcodes/packunpack.tz b/tests_python/contracts_009/opcodes/packunpack.tz new file mode 100644 index 0000000000000000000000000000000000000000..ad313fa8aee68def15865de26f2451f2204a2a6d --- /dev/null +++ b/tests_python/contracts_009/opcodes/packunpack.tz @@ -0,0 +1,6 @@ +parameter (pair (pair (pair string (list int)) (set nat)) bytes) ; +storage unit ; +code { CAR ; UNPAIR ; DIP { DUP } ; + PACK ; ASSERT_CMPEQ ; + UNPACK (pair (pair string (list int)) (set nat)) ; ASSERT_SOME ; DROP ; + UNIT ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/packunpack_rev.tz b/tests_python/contracts_009/opcodes/packunpack_rev.tz new file mode 100644 index 0000000000000000000000000000000000000000..9c94cd68dcc14d1ededaec780da85454d02b9aa9 --- /dev/null +++ b/tests_python/contracts_009/opcodes/packunpack_rev.tz @@ -0,0 +1,43 @@ +parameter (pair + int + nat + string + bytes + mutez + bool + key_hash + timestamp address); +storage unit ; +code { CAR; + # Check the int + DUP; CAR; DIP { UNPAIR; }; PACK; UNPACK int; ASSERT_SOME; ASSERT_CMPEQ; + # Check the nat + DUP; CAR; DIP { UNPAIR; }; PACK; UNPACK nat; ASSERT_SOME; ASSERT_CMPEQ; + # Check the string + DUP; CAR; DIP { UNPAIR; }; PACK; UNPACK string; ASSERT_SOME; ASSERT_CMPEQ; + # Check the bytes + DUP; CAR; DIP { UNPAIR; }; PACK; UNPACK bytes; ASSERT_SOME; ASSERT_CMPEQ; + # Check the mutez + DUP; CAR; DIP { UNPAIR; }; PACK; UNPACK mutez; ASSERT_SOME; ASSERT_CMPEQ; + # Check the bool + DUP; CAR; DIP { UNPAIR; }; PACK; UNPACK bool; ASSERT_SOME; ASSERT_CMPEQ; + # Check the key_hash + DUP; CAR; DIP { UNPAIR; }; PACK; UNPACK key_hash; ASSERT_SOME; ASSERT_CMPEQ; + # Check the timestamp + DUP; CAR; DIP { UNPAIR; }; PACK; UNPACK timestamp; ASSERT_SOME; ASSERT_CMPEQ; + # Check the address + DUP; PACK; UNPACK address; ASSERT_SOME; ASSERT_CMPEQ; + + # Assert failure modes of unpack + PUSH int 0; PACK; UNPACK nat; ASSERT_SOME; DROP; + PUSH int -1; PACK; UNPACK nat; ASSERT_NONE; + + # Try deserializing invalid byte sequence (no magic number) + PUSH bytes 0x; UNPACK nat; ASSERT_NONE; + PUSH bytes 0x04; UNPACK nat; ASSERT_NONE; + + # Assert failure for byte sequences that do not correspond to + # any micheline value + PUSH bytes 0x05; UNPACK nat; ASSERT_NONE; + + UNIT ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/packunpack_rev_cty.tz b/tests_python/contracts_009/opcodes/packunpack_rev_cty.tz new file mode 100644 index 0000000000000000000000000000000000000000..7ca7ca64a3c32c868704937c616dcd3977fdb02c --- /dev/null +++ b/tests_python/contracts_009/opcodes/packunpack_rev_cty.tz @@ -0,0 +1,31 @@ +parameter (pair key unit signature (option signature) (list unit) (set bool) (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes)); +storage unit ; +# for each uncomparable type t (we take an arbitrary parameter for +# parametric data-types e.g. pair, list), +# that is packable (which excludes big_map, operation, and contract) +# this contract receives a parameter v_t. +# it verifies that pack v_t == pack (unpack (pack v_t)) +code { CAR; + # packable uncomparable types + # checking: key + DUP; CAR; DIP { UNPAIR; }; PACK; DIP { PACK; UNPACK key; ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + # checking: unit + DUP; CAR; DIP { UNPAIR; }; PACK; DIP { PACK; UNPACK unit; ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + # checking: signature + DUP; CAR; DIP { UNPAIR; }; PACK; DIP { PACK; UNPACK (signature); ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + # checking: option signature + DUP; CAR; DIP { UNPAIR; }; PACK; DIP { PACK; UNPACK (option signature); ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + # checking: list unit + DUP; CAR; DIP { UNPAIR; }; PACK; DIP { PACK; UNPACK (list unit); ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + # checking: set bool + DUP; CAR; DIP { UNPAIR; }; PACK; DIP { PACK; UNPACK (set bool); ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + # checking: pair int int + DUP; CAR; DIP { UNPAIR; }; PACK; DIP { PACK; UNPACK (pair int int); ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + # checking: or key_hash timestamp + DUP; CAR; DIP { UNPAIR; }; PACK; DIP { PACK; UNPACK (or key_hash timestamp); ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + # checking: map int string + DUP; CAR; DIP { UNPAIR; }; PACK; DIP { PACK; UNPACK (map int string); ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + # checking: lambda string bytes + DUP; PACK; DIP { PACK; UNPACK (lambda string bytes); ASSERT_SOME; PACK; }; ASSERT_CMPEQ; + + UNIT ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/pair_id.tz b/tests_python/contracts_009/opcodes/pair_id.tz new file mode 100644 index 0000000000000000000000000000000000000000..3bfedf2d8cdf594ad1b9f603291f73abc864f22a --- /dev/null +++ b/tests_python/contracts_009/opcodes/pair_id.tz @@ -0,0 +1,3 @@ +parameter (pair bool bool); +storage (option (pair bool bool)); +code {CAR; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/pairing_check.tz b/tests_python/contracts_009/opcodes/pairing_check.tz new file mode 100644 index 0000000000000000000000000000000000000000..3b829f315c051140f1e248744652eaaf9f067b6c --- /dev/null +++ b/tests_python/contracts_009/opcodes/pairing_check.tz @@ -0,0 +1,3 @@ +parameter (list (pair bls12_381_g1 bls12_381_g2)); +storage (option bool); +code {CAR; PAIRING_CHECK; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/pexec.tz b/tests_python/contracts_009/opcodes/pexec.tz new file mode 100644 index 0000000000000000000000000000000000000000..eab0c71b4f59d31213510ca84f01e59c58be61bb --- /dev/null +++ b/tests_python/contracts_009/opcodes/pexec.tz @@ -0,0 +1,6 @@ +parameter nat; +storage nat; +code { + LAMBDA (pair nat nat) nat + {UNPAIR ; ADD}; + SWAP; UNPAIR ; DIP { APPLY } ; EXEC ; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/pexec_2.tz b/tests_python/contracts_009/opcodes/pexec_2.tz new file mode 100644 index 0000000000000000000000000000000000000000..d64f7442f50e1a70e0f8e7a5b19d4e3518c6ab84 --- /dev/null +++ b/tests_python/contracts_009/opcodes/pexec_2.tz @@ -0,0 +1,11 @@ +parameter int; +storage (list int); +code { + UNPAIR @p @s ; # p :: s + LAMBDA (pair int (pair int int)) int + { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL }; # l :: p :: s + SWAP ; APPLY ; # l :: s + PUSH int 3 ; APPLY ; # l :: s + SWAP ; MAP { DIP { DUP } ; EXEC } ; # s :: l + DIP { DROP } ; # s + NIL operation; PAIR }; diff --git a/tests_python/contracts_009/opcodes/proxy.tz b/tests_python/contracts_009/opcodes/proxy.tz new file mode 100644 index 0000000000000000000000000000000000000000..185bbcd321cc48a016573c0287ab6ec4c7a0909e --- /dev/null +++ b/tests_python/contracts_009/opcodes/proxy.tz @@ -0,0 +1,13 @@ +/* This proxy contract transfers the received amount to the contract given as parameter. + It is used to test the SOURCE and SENDER opcodes; see source.tz and sender.tz. */ +parameter (contract unit) ; +storage unit ; +code{ + UNPAIR; + AMOUNT ; + UNIT ; + TRANSFER_TOKENS; + DIP {NIL operation} ; + CONS; + PAIR + } \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/ret_int.tz b/tests_python/contracts_009/opcodes/ret_int.tz new file mode 100644 index 0000000000000000000000000000000000000000..720a99568e96e96bb01b98fb79141b647fd3e399 --- /dev/null +++ b/tests_python/contracts_009/opcodes/ret_int.tz @@ -0,0 +1,3 @@ +parameter unit; +storage (option nat); +code {DROP; PUSH nat 300; SOME; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/reverse.tz b/tests_python/contracts_009/opcodes/reverse.tz new file mode 100644 index 0000000000000000000000000000000000000000..5a851f3e29d0181f1db6d12b420a541e0b86f41a --- /dev/null +++ b/tests_python/contracts_009/opcodes/reverse.tz @@ -0,0 +1,5 @@ +parameter (list string); +storage (list string); +code { CAR; NIL string; SWAP; + ITER {CONS}; + NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/reverse_loop.tz b/tests_python/contracts_009/opcodes/reverse_loop.tz new file mode 100644 index 0000000000000000000000000000000000000000..d8117135c984e90094f924b7820803033aff543e --- /dev/null +++ b/tests_python/contracts_009/opcodes/reverse_loop.tz @@ -0,0 +1,5 @@ +parameter (list string); +storage (list string); +code { CAR; NIL string; SWAP; PUSH bool True; + LOOP { IF_CONS {SWAP; DIP{CONS}; PUSH bool True} {NIL string; PUSH bool False}}; + DROP; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/sapling_empty_state.tz b/tests_python/contracts_009/opcodes/sapling_empty_state.tz new file mode 100644 index 0000000000000000000000000000000000000000..6a568da92dd3d2e40000698df82ba136dacaf5a3 --- /dev/null +++ b/tests_python/contracts_009/opcodes/sapling_empty_state.tz @@ -0,0 +1,3 @@ +parameter unit; +storage (sapling_state 8); +code { DROP; SAPLING_EMPTY_STATE 8; NIL operation; PAIR; }; diff --git a/tests_python/contracts_009/opcodes/self.tz b/tests_python/contracts_009/opcodes/self.tz new file mode 100644 index 0000000000000000000000000000000000000000..d96457fd1331035930298a1fdbeafd81b2840d29 --- /dev/null +++ b/tests_python/contracts_009/opcodes/self.tz @@ -0,0 +1,3 @@ +parameter unit ; +storage address ; +code { DROP ; SELF ; ADDRESS ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/self_address.tz b/tests_python/contracts_009/opcodes/self_address.tz new file mode 100644 index 0000000000000000000000000000000000000000..73f4779bab249cc9083a1e0d3fa0c2c1c36bf529 --- /dev/null +++ b/tests_python/contracts_009/opcodes/self_address.tz @@ -0,0 +1,11 @@ +parameter unit; +storage unit; +code { + DROP; + LAMBDA unit address { DROP; SELF_ADDRESS }; + UNIT; + EXEC; + SELF; ADDRESS; + ASSERT_CMPEQ; + UNIT; NIL operation; PAIR + } diff --git a/tests_python/contracts_009/opcodes/self_with_default_entrypoint.tz b/tests_python/contracts_009/opcodes/self_with_default_entrypoint.tz new file mode 100644 index 0000000000000000000000000000000000000000..47f848c0d5a15ad00189075b19334c2021a4a9d4 --- /dev/null +++ b/tests_python/contracts_009/opcodes/self_with_default_entrypoint.tz @@ -0,0 +1,19 @@ +parameter (or (or (nat %A) (bool %B)) (or %maybe_C (unit %default) (string %C))); +storage unit; +code { + DROP; + SELF; DROP; + # Refers to entrypoint A of the current contract. + SELF %A; DROP; + # Refers to the default entry of the current contract + SELF %default; PACK; + # "SELF" w/o annotation also refers to the default + # entry of the current contract. Internally, they are equal. + SELF; PACK; ASSERT_CMPEQ; + # The following instruction would not typecheck: + # SELF %D, + # since there is no entrypoint D. + UNIT; + NIL operation; + PAIR; + } diff --git a/tests_python/contracts_009/opcodes/self_with_entrypoint.tz b/tests_python/contracts_009/opcodes/self_with_entrypoint.tz new file mode 100644 index 0000000000000000000000000000000000000000..ea6f8e1898e29ff5ebc53b9434ec7b1b8f056e17 --- /dev/null +++ b/tests_python/contracts_009/opcodes/self_with_entrypoint.tz @@ -0,0 +1,26 @@ +parameter (or (or (nat %A) (bool %B)) (or %maybe_C (unit %Z) (string %C))); +storage unit; +code { + DROP; + # Refers to entrypoint A of the current contract. + SELF %A; PACK @Apacked; + # Refers to the default entry of the current contract + SELF %default; PACK @defpacked; DUP; DIP { SWAP }; ASSERT_CMPNEQ; + # "SELF" w/o annotation also refers to the default + # entry of the current contract + SELF; PACK @selfpacked; ASSERT_CMPEQ; + + # Verify the types of the different entrypoints. CAST is noop + # if its argument is convertible with the type of the top of + # the stack. + SELF %A; CAST (contract nat); DROP; + SELF %B; CAST (contract bool); DROP; + SELF %maybe_C; CAST (contract (or (unit) (string))); DROP; + SELF %Z; CAST (contract unit); DROP; + SELF; CAST (contract (or (or (nat %A) (bool %B)) (or %maybe_C (unit %Z) (string %C)))); DROP; + SELF %default; CAST (contract (or (or (nat %A) (bool %B)) (or %maybe_C (unit %Z) (string %C)))); DROP; + + UNIT; + NIL operation; + PAIR; + } diff --git a/tests_python/contracts_009/opcodes/sender.tz b/tests_python/contracts_009/opcodes/sender.tz new file mode 100644 index 0000000000000000000000000000000000000000..fb174179aca53f366f19723e6df11924d597f26a --- /dev/null +++ b/tests_python/contracts_009/opcodes/sender.tz @@ -0,0 +1,8 @@ +parameter unit ; +storage address ; +code{ + DROP ; + SENDER; + NIL operation ; + PAIR + } diff --git a/tests_python/contracts_009/opcodes/set_car.tz b/tests_python/contracts_009/opcodes/set_car.tz new file mode 100644 index 0000000000000000000000000000000000000000..460b3385674365acf7e56b1b5e9c99c259ce053b --- /dev/null +++ b/tests_python/contracts_009/opcodes/set_car.tz @@ -0,0 +1,3 @@ +parameter string; +storage (pair (string %s) (nat %n)); +code { DUP; CDR; DIP{CAR}; SET_CAR %s; NIL operation; PAIR }; diff --git a/tests_python/contracts_009/opcodes/set_cdr.tz b/tests_python/contracts_009/opcodes/set_cdr.tz new file mode 100644 index 0000000000000000000000000000000000000000..d725756bbcaa8fecf7376b26895e7f5a40607e59 --- /dev/null +++ b/tests_python/contracts_009/opcodes/set_cdr.tz @@ -0,0 +1,3 @@ +parameter nat; +storage (pair (string %s) (nat %n)); +code { DUP; CDR; DIP{CAR}; SET_CDR %n; NIL operation; PAIR }; diff --git a/tests_python/contracts_009/opcodes/set_delegate.tz b/tests_python/contracts_009/opcodes/set_delegate.tz new file mode 100644 index 0000000000000000000000000000000000000000..a7e051e50494a6c87e9e020ccf7500bc45ffbc60 --- /dev/null +++ b/tests_python/contracts_009/opcodes/set_delegate.tz @@ -0,0 +1,9 @@ +parameter (option key_hash); +storage unit; +code { + UNPAIR; + SET_DELEGATE; + DIP {NIL operation}; + CONS; + PAIR + } diff --git a/tests_python/contracts_009/opcodes/set_id.tz b/tests_python/contracts_009/opcodes/set_id.tz new file mode 100644 index 0000000000000000000000000000000000000000..ede301b0e9794bead96057db0fdfe120e365c197 --- /dev/null +++ b/tests_python/contracts_009/opcodes/set_id.tz @@ -0,0 +1,3 @@ +parameter (set string); +storage (set string); +code { CAR ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/set_iter.tz b/tests_python/contracts_009/opcodes/set_iter.tz new file mode 100644 index 0000000000000000000000000000000000000000..55d8ae34aba735fbc12def5239f0273343c5dfbf --- /dev/null +++ b/tests_python/contracts_009/opcodes/set_iter.tz @@ -0,0 +1,3 @@ +parameter (set int); +storage int; +code { CAR; PUSH int 0; SWAP; ITER { ADD }; NIL operation; PAIR } diff --git a/tests_python/contracts_009/opcodes/set_member.tz b/tests_python/contracts_009/opcodes/set_member.tz new file mode 100644 index 0000000000000000000000000000000000000000..ae97cce14345e1cf9dd88a41bb766d08ded2a7a7 --- /dev/null +++ b/tests_python/contracts_009/opcodes/set_member.tz @@ -0,0 +1,3 @@ +parameter string; +storage (pair (set string) (option bool)); +code {DUP; DUP; CAR; DIP{CDAR}; MEM; SOME; DIP {CDAR}; SWAP; PAIR ; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/set_size.tz b/tests_python/contracts_009/opcodes/set_size.tz new file mode 100644 index 0000000000000000000000000000000000000000..aa055cb0219283f086befa46c1714a7259d273ba --- /dev/null +++ b/tests_python/contracts_009/opcodes/set_size.tz @@ -0,0 +1,3 @@ +parameter (set int); +storage nat; +code {CAR; SIZE; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/sha3.tz b/tests_python/contracts_009/opcodes/sha3.tz new file mode 100644 index 0000000000000000000000000000000000000000..3ce8cde000e31240a55f08e822aef4f3ec48a8d8 --- /dev/null +++ b/tests_python/contracts_009/opcodes/sha3.tz @@ -0,0 +1,8 @@ +storage (option bytes); +parameter bytes; +code + { + CAR; + SHA3; SOME; + NIL operation; PAIR + } diff --git a/tests_python/contracts_009/opcodes/shifts.tz b/tests_python/contracts_009/opcodes/shifts.tz new file mode 100644 index 0000000000000000000000000000000000000000..71964750c0b8070272f0039332cca69b02219c45 --- /dev/null +++ b/tests_python/contracts_009/opcodes/shifts.tz @@ -0,0 +1,18 @@ +parameter (or (pair nat nat) (pair nat nat)); +storage (option nat); +# this contract takes either (Left a b) and stores (a << b) +# or (Right a b) and stores (a >> b). +# i.e., in the first case, the first component shifted to the left by +# the second, and the second case, component shifted to the right by +# the second. +code { CAR; + IF_LEFT { + UNPAIR; LSL; + } + { + UNPAIR; LSR; + }; + SOME; + NIL operation; + PAIR; + }; diff --git a/tests_python/contracts_009/opcodes/slice.tz b/tests_python/contracts_009/opcodes/slice.tz new file mode 100644 index 0000000000000000000000000000000000000000..3461bb5533d1cb3d52b98575474431cb4bc38588 --- /dev/null +++ b/tests_python/contracts_009/opcodes/slice.tz @@ -0,0 +1,5 @@ +parameter (pair nat nat); +storage (option string); +code { UNPAIR; SWAP; + IF_SOME {SWAP; UNPAIR; SLICE;} {DROP; NONE string;}; + NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/slice_bytes.tz b/tests_python/contracts_009/opcodes/slice_bytes.tz new file mode 100644 index 0000000000000000000000000000000000000000..c0f60f358765de3ce16d2bec7b32e7f1f51b7454 --- /dev/null +++ b/tests_python/contracts_009/opcodes/slice_bytes.tz @@ -0,0 +1,5 @@ +parameter (pair nat nat); +storage (option bytes); +code { UNPAIR; SWAP; + IF_SOME {SWAP; UNPAIR; SLICE;} {DROP; NONE bytes;}; + NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/slices.tz b/tests_python/contracts_009/opcodes/slices.tz new file mode 100644 index 0000000000000000000000000000000000000000..fa76827261c03faabee57b057abfa579769ec075 --- /dev/null +++ b/tests_python/contracts_009/opcodes/slices.tz @@ -0,0 +1,11 @@ +parameter (pair bytes signature) ; +storage key ; +code { DUP ; + CAAR ; DUP ; SIZE ; PUSH nat 128 ; SWAP ; SUB ; ISNAT ; IF_SOME {} { FAIL } ; + PUSH nat 128 ; SLICE @payload ; ASSERT_SOME ; + DUP ; DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; SHA256 ; ASSERT_CMPEQ } ; + DUP ; DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; BLAKE2B ; ASSERT_CMPEQ } ; + DUP ; DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; SHA512 ; ASSERT_CMPEQ } ; + DIP { DUP ; CDR ; DIP { DUP ; CADR }} ; SWAP ; DIP { SWAP } ; CHECK_SIGNATURE ; ASSERT ; + CDR ; DUP ; HASH_KEY ; IMPLICIT_ACCOUNT ; BALANCE ; UNIT ; TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/source.tz b/tests_python/contracts_009/opcodes/source.tz new file mode 100644 index 0000000000000000000000000000000000000000..fc3c642027d3b9d0985dc0a97fdfdf7c097d0b35 --- /dev/null +++ b/tests_python/contracts_009/opcodes/source.tz @@ -0,0 +1,10 @@ +parameter unit ; + +storage address ; + +code{ + DROP ; + SOURCE; + NIL operation ; + PAIR + } \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/split_bytes.tz b/tests_python/contracts_009/opcodes/split_bytes.tz new file mode 100644 index 0000000000000000000000000000000000000000..f3b623b3c4b313b906ae7f11aaf8c2a43a1830f0 --- /dev/null +++ b/tests_python/contracts_009/opcodes/split_bytes.tz @@ -0,0 +1,16 @@ +parameter bytes ; +storage (list bytes) ; +code { UNPAIR ; + DIP { NIL bytes ; SWAP ; ITER { CONS } } ; + DUP ; SIZE ; PUSH nat 0 ; CMPNEQ ; + DIP { PUSH @index nat 0 } ; + LOOP + { PAIR ; DUP ; + DIP { UNPAIR ; DIP { PUSH nat 1 } ; SLICE ; ASSERT_SOME ; CONS @storage } ; + UNPAIR ; + PUSH nat 1 ; ADD @index ; + DUP ; DIP { DIP { DUP } ; SWAP ; SIZE ; CMPNEQ } ; SWAP ; + } ; + DROP ; DROP ; + NIL bytes ; SWAP ; ITER { CONS } ; + NIL operation ; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/split_string.tz b/tests_python/contracts_009/opcodes/split_string.tz new file mode 100644 index 0000000000000000000000000000000000000000..909ba604742d89dfad2ff5adf8049e6bdba6b87e --- /dev/null +++ b/tests_python/contracts_009/opcodes/split_string.tz @@ -0,0 +1,16 @@ +parameter string ; +storage (list string) ; +code { UNPAIR ; + DIP { NIL string ; SWAP ; ITER { CONS } } ; + DUP ; SIZE ; PUSH nat 0 ; CMPNEQ ; + DIP { PUSH @index nat 0 } ; + LOOP + { PAIR ; DUP ; + DIP { UNPAIR ; DIP { PUSH nat 1 } ; SLICE ; ASSERT_SOME ; CONS @storage } ; + UNPAIR ; + PUSH nat 1 ; ADD @index ; + DUP ; DIP { DIP { DUP } ; SWAP ; SIZE ; CMPNEQ } ; SWAP ; + } ; + DROP ; DROP ; + NIL string ; SWAP ; ITER { CONS } ; + NIL operation ; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/store_bls12_381_fr.tz b/tests_python/contracts_009/opcodes/store_bls12_381_fr.tz new file mode 100644 index 0000000000000000000000000000000000000000..b40aa9b4ad1c5471b03c7e5091ac8ffb0f4c3afe --- /dev/null +++ b/tests_python/contracts_009/opcodes/store_bls12_381_fr.tz @@ -0,0 +1,3 @@ +parameter bls12_381_fr; +storage (option (bls12_381_fr)); +code {CAR; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/store_bls12_381_g1.tz b/tests_python/contracts_009/opcodes/store_bls12_381_g1.tz new file mode 100644 index 0000000000000000000000000000000000000000..1bc148f54282b6660a983f885563312028ba157f --- /dev/null +++ b/tests_python/contracts_009/opcodes/store_bls12_381_g1.tz @@ -0,0 +1,3 @@ +parameter bls12_381_g1; +storage (option (bls12_381_g1)); +code {CAR; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/store_bls12_381_g2.tz b/tests_python/contracts_009/opcodes/store_bls12_381_g2.tz new file mode 100644 index 0000000000000000000000000000000000000000..b640877062652c865c708473427b5a3e0edabcc1 --- /dev/null +++ b/tests_python/contracts_009/opcodes/store_bls12_381_g2.tz @@ -0,0 +1,3 @@ +parameter bls12_381_g2; +storage (option (bls12_381_g2)); +code {CAR; SOME; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/store_input.tz b/tests_python/contracts_009/opcodes/store_input.tz new file mode 100644 index 0000000000000000000000000000000000000000..4eee565ca2e957d2b7f225eae5481edee6a24932 --- /dev/null +++ b/tests_python/contracts_009/opcodes/store_input.tz @@ -0,0 +1,3 @@ +parameter string; +storage string; +code {CAR; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/store_now.tz b/tests_python/contracts_009/opcodes/store_now.tz new file mode 100644 index 0000000000000000000000000000000000000000..1a868ac06f148eba683490e79cf1250cd670b4f1 --- /dev/null +++ b/tests_python/contracts_009/opcodes/store_now.tz @@ -0,0 +1,3 @@ +parameter unit; +storage timestamp; +code {DROP; NOW; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/str_id.tz b/tests_python/contracts_009/opcodes/str_id.tz new file mode 100644 index 0000000000000000000000000000000000000000..f9e0710c328f583b16bd8276421b1d3de9e6070a --- /dev/null +++ b/tests_python/contracts_009/opcodes/str_id.tz @@ -0,0 +1,3 @@ +parameter string; +storage (option string); +code { CAR ; SOME ; NIL operation ; PAIR }; diff --git a/tests_python/contracts_009/opcodes/sub_timestamp_delta.tz b/tests_python/contracts_009/opcodes/sub_timestamp_delta.tz new file mode 100644 index 0000000000000000000000000000000000000000..f154e952414f49347c549a39bc646e1463e730f1 --- /dev/null +++ b/tests_python/contracts_009/opcodes/sub_timestamp_delta.tz @@ -0,0 +1,3 @@ +parameter (pair timestamp int); +storage timestamp; +code { CAR; DUP; CAR; DIP{CDR}; SUB; NIL operation; PAIR} diff --git a/tests_python/contracts_009/opcodes/subset.tz b/tests_python/contracts_009/opcodes/subset.tz new file mode 100644 index 0000000000000000000000000000000000000000..a16ef1695cb2339b2fccd7c5d7272bf033d71a0f --- /dev/null +++ b/tests_python/contracts_009/opcodes/subset.tz @@ -0,0 +1,12 @@ +parameter (pair (set string) (set string)); +storage bool; +code { CAR; DUP; CDR; DIP{CAR}; # Unpack lists + PUSH bool True; + PAIR; SWAP; # Setup accumulator + ITER { DIP{ DUP; DUP; CDR; + DIP{CAR; DIP{CDR}}}; + MEM; # Check membership + AND; # Combine accumulator and input + PAIR}; + CAR; # Get the accumulator value + NIL operation; PAIR} # Calling convention diff --git a/tests_python/contracts_009/opcodes/tez_add_sub.tz b/tests_python/contracts_009/opcodes/tez_add_sub.tz new file mode 100644 index 0000000000000000000000000000000000000000..39eba1d1627574425c673dbd8ffa8d8f29088a40 --- /dev/null +++ b/tests_python/contracts_009/opcodes/tez_add_sub.tz @@ -0,0 +1,5 @@ +parameter (pair mutez mutez); +storage (option (pair mutez mutez)); +code {CAR; DUP; DUP; CAR; DIP{CDR}; ADD; + DIP{DUP; CAR; DIP{CDR}; SUB}; + PAIR; SOME; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/ticket_bad.tz b/tests_python/contracts_009/opcodes/ticket_bad.tz new file mode 100644 index 0000000000000000000000000000000000000000..e183ac5278b5a5c52913d62e39866326a0a7289f --- /dev/null +++ b/tests_python/contracts_009/opcodes/ticket_bad.tz @@ -0,0 +1,5 @@ +# Although this contract is correctly typed, originating it with a forged +# ticket should be refused +parameter unit; +storage (ticket nat); +code { CDR ; NIL operation ; PAIR } diff --git a/tests_python/contracts_009/opcodes/ticket_big_store.tz b/tests_python/contracts_009/opcodes/ticket_big_store.tz new file mode 100644 index 0000000000000000000000000000000000000000..6d1de845235e41984b6882e6f43324a0a5723165 --- /dev/null +++ b/tests_python/contracts_009/opcodes/ticket_big_store.tz @@ -0,0 +1,3 @@ +parameter nat ; +storage (big_map unit (ticket nat)); +code { UNPAIR ; PUSH nat 1 ; SWAP ; TICKET ; SOME ; UNIT ; UPDATE ; NIL operation ; PAIR } ; diff --git a/tests_python/contracts_009/opcodes/ticket_join.tz b/tests_python/contracts_009/opcodes/ticket_join.tz new file mode 100644 index 0000000000000000000000000000000000000000..3aef469a48c5731a5f429718aae702e43bef5a95 --- /dev/null +++ b/tests_python/contracts_009/opcodes/ticket_join.tz @@ -0,0 +1,7 @@ +parameter (ticket nat); +storage (option (ticket nat)); +code { UNPAIR ; SWAP ; + IF_NONE {} { PAIR ; JOIN_TICKETS ; ASSERT_SOME } ; + SOME ; + NIL operation ; + PAIR } diff --git a/tests_python/contracts_009/opcodes/ticket_read.tz b/tests_python/contracts_009/opcodes/ticket_read.tz new file mode 100644 index 0000000000000000000000000000000000000000..c41176a5fee06645cd20eb99a2d89590f7e520d3 --- /dev/null +++ b/tests_python/contracts_009/opcodes/ticket_read.tz @@ -0,0 +1,8 @@ +parameter (ticket nat); +storage address; +code { CAR ; + READ_TICKET ; DIP { DROP } ; UNPAIR ; DIP { UNPAIR } ; + DIIP { PUSH nat 1 ; ASSERT_CMPEQ } ; + DIP { PUSH nat 42 ; ASSERT_CMPEQ } ; + NIL operation ; + PAIR } diff --git a/tests_python/contracts_009/opcodes/ticket_split.tz b/tests_python/contracts_009/opcodes/ticket_split.tz new file mode 100644 index 0000000000000000000000000000000000000000..a2587beb717edfee8b51e6524a13eb27608be83a --- /dev/null +++ b/tests_python/contracts_009/opcodes/ticket_split.tz @@ -0,0 +1,11 @@ +parameter (ticket nat) ; +storage unit; +code + { CAR ; + PUSH (pair nat nat) (Pair 1 2) ; SWAP; + SPLIT_TICKET; ASSERT_SOME; UNPAIR; + READ_TICKET; CDDR; PUSH nat 1; ASSERT_CMPEQ; + DROP; + READ_TICKET; CDDR; PUSH nat 2; ASSERT_CMPEQ; + DROP; + UNIT ; NIL operation ; PAIR } ; diff --git a/tests_python/contracts_009/opcodes/ticket_store-2.tz b/tests_python/contracts_009/opcodes/ticket_store-2.tz new file mode 100644 index 0000000000000000000000000000000000000000..cab3dd79d0123db3afe61753e0515d3c1dd69e63 --- /dev/null +++ b/tests_python/contracts_009/opcodes/ticket_store-2.tz @@ -0,0 +1,3 @@ +parameter (option (ticket nat)) ; +storage (option (ticket nat)); +code { CAR ; NIL operation ; PAIR } ; diff --git a/tests_python/contracts_009/opcodes/ticket_store.tz b/tests_python/contracts_009/opcodes/ticket_store.tz new file mode 100644 index 0000000000000000000000000000000000000000..926a04aa1e88c0a531d9dae9bc5f7f916be87cc6 --- /dev/null +++ b/tests_python/contracts_009/opcodes/ticket_store.tz @@ -0,0 +1,3 @@ +parameter (ticket nat) ; +storage (option (ticket nat)); +code { CAR ; SOME ; NIL operation ; PAIR } ; diff --git a/tests_python/contracts_009/opcodes/ticketer-2.tz b/tests_python/contracts_009/opcodes/ticketer-2.tz new file mode 100644 index 0000000000000000000000000000000000000000..bce940ccabe270ed748e9c49ba81489fde35b1ea --- /dev/null +++ b/tests_python/contracts_009/opcodes/ticketer-2.tz @@ -0,0 +1,9 @@ +parameter (pair (pair address nat) nat) ; +storage unit; +code { CAR ; UNPAIR ; UNPAIR ; + CONTRACT (ticket nat) ; ASSERT_SOME ; + DIP { TICKET } ; + SWAP ; DIP { PUSH mutez 0 } ; + TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; + UNIT ; SWAP ; PAIR } diff --git a/tests_python/contracts_009/opcodes/ticketer.tz b/tests_python/contracts_009/opcodes/ticketer.tz new file mode 100644 index 0000000000000000000000000000000000000000..c8ec4565398a43c462dcf9da9d03317e2b889563 --- /dev/null +++ b/tests_python/contracts_009/opcodes/ticketer.tz @@ -0,0 +1,10 @@ +parameter address; +storage nat; +code { UNPAIR ; DIP { DUP } ; + SWAP ; + PUSH nat 1 ; SWAP ; + TICKET ; + DIP { CONTRACT (ticket nat) ; ASSERT_SOME ; PUSH mutez 0 } ; + TRANSFER_TOKENS ; + NIL operation ; SWAP ; CONS ; + PAIR } diff --git a/tests_python/contracts_009/opcodes/transfer_amount.tz b/tests_python/contracts_009/opcodes/transfer_amount.tz new file mode 100644 index 0000000000000000000000000000000000000000..973c64f04dccb20867ab115eba82fba462531911 --- /dev/null +++ b/tests_python/contracts_009/opcodes/transfer_amount.tz @@ -0,0 +1,3 @@ +parameter unit; +storage mutez; +code { DROP; AMOUNT; NIL operation; PAIR }; diff --git a/tests_python/contracts_009/opcodes/transfer_tokens.tz b/tests_python/contracts_009/opcodes/transfer_tokens.tz new file mode 100644 index 0000000000000000000000000000000000000000..599b4dae180fc718e2887d909eae3661c4367322 --- /dev/null +++ b/tests_python/contracts_009/opcodes/transfer_tokens.tz @@ -0,0 +1,5 @@ +parameter (contract unit); +storage unit; +code { CAR; DIP{UNIT}; PUSH mutez 100000000; UNIT; + TRANSFER_TOKENS; + NIL operation; SWAP; CONS; PAIR}; diff --git a/tests_python/contracts_009/opcodes/uncomb.tz b/tests_python/contracts_009/opcodes/uncomb.tz new file mode 100644 index 0000000000000000000000000000000000000000..84c3ced7ca9cf32bc149a2023243d48ce6a0f585 --- /dev/null +++ b/tests_python/contracts_009/opcodes/uncomb.tz @@ -0,0 +1,8 @@ +parameter (pair nat nat nat); +storage nat; +code { CAR ; + UNPAIR 3 ; + PUSH nat 100 ; MUL ; + SWAP ; PUSH nat 10 ; MUL ; + ADD ; ADD ; + NIL operation ; PAIR ; } diff --git a/tests_python/contracts_009/opcodes/unpair.tz b/tests_python/contracts_009/opcodes/unpair.tz new file mode 100644 index 0000000000000000000000000000000000000000..b45f30a03d382b80b5b9644ac08fdf29214fcb43 --- /dev/null +++ b/tests_python/contracts_009/opcodes/unpair.tz @@ -0,0 +1,71 @@ +parameter (unit :param_unit); +storage (unit :u1); +code { DROP ; + + # No annotation + UNIT; UNIT; PAIR; UNPAIR; DROP 2; + + # Variable annotations are overriden by UNPAIR + UNIT @b; UNIT @a; PAIR; UNPAIR @c @d; DROP 2; + + UNIT @b; UNIT @a; PAIR %@ %@; + DUP; UNPAIR %a %b; DROP 2; + DUP; UNPAIR % %b; DROP 2; + DUP; UNPAIR %a %; DROP 2; + DUP; UNPAIR % %; DROP 2; + DUP; UNPAIR %a; DROP 2; + DUP; UNPAIR %; DROP 2; + DUP; UNPAIR; DROP 2; + DUP; UNPAIR %a %b @a @b; DROP 2; + DUP; UNPAIR @a @b %a %b; DROP 2; + DUP; UNPAIR @a @% %a %b; DROP 2; + DUP; UNPAIR @% @% %a %b; DROP 2; + DUP; UNPAIR @% @b %a %b; DROP 2; + DROP; + + # Same test with non-matching field and variable annotations + UNIT @d; UNIT @c; PAIR %a %b; + DUP; UNPAIR %a %b; DROP 2; + DUP; UNPAIR % %b; DROP 2; + DUP; UNPAIR %a %; DROP 2; + DUP; UNPAIR % %; DROP 2; + DUP; UNPAIR %a; DROP 2; + DUP; UNPAIR %; DROP 2; + DUP; UNPAIR; DROP 2; + DUP; UNPAIR %a %b @a @b; DROP 2; + DUP; UNPAIR @a @b %a %b; DROP 2; + DUP; UNPAIR @a @% %a %b; DROP 2; + DUP; UNPAIR @% @% %a %b; DROP 2; + DUP; UNPAIR @% @b %a %b; DROP 2; + DROP; + + # Same tests without the variable annotations in input + UNIT; UNIT; PAIR %a %b; + DUP; UNPAIR %a %b; DROP 2; + DUP; UNPAIR % %b; DROP 2; + DUP; UNPAIR %a %; DROP 2; + DUP; UNPAIR % %; DROP 2; + DUP; UNPAIR %a; DROP 2; + DUP; UNPAIR %; DROP 2; + DUP; UNPAIR; DROP 2; + DUP; UNPAIR %a %b @a @b; DROP 2; + DUP; UNPAIR @a @b %a %b; DROP 2; + DUP; UNPAIR @a @% %a %b; DROP 2; + DUP; UNPAIR @% @% %a %b; DROP 2; + DUP; UNPAIR @% @b %a %b; DROP 2; + DROP; + + # Tests for @%% + UNIT; UNIT; PAIR %a %b @p; + DUP; UNPAIR @%% @b; DROP 2; + DUP; UNPAIR @a @%%; DROP 2; + DUP; UNPAIR @%% @%%; DROP 2; + DUP; UNPAIR @% @%%; DROP 2; + DUP; UNPAIR @%% @%; DROP 2; + DROP; + + # Swapping variable annotations + UNIT @b; UNIT @a; PAIR @c; UNPAIR @b @a; DROP 2; + + # End of test + UNIT; NIL operation; PAIR } \ No newline at end of file diff --git a/tests_python/contracts_009/opcodes/update_big_map.tz b/tests_python/contracts_009/opcodes/update_big_map.tz new file mode 100644 index 0000000000000000000000000000000000000000..c403975a38fb1d0570b61a2c1fa90668a16f6b80 --- /dev/null +++ b/tests_python/contracts_009/opcodes/update_big_map.tz @@ -0,0 +1,6 @@ +storage (pair (big_map string string) unit); +parameter (map string (option string)); +# this contract the stored big_map according to the map taken in parameter +code { UNPAPAIR; + ITER { UNPAIR; UPDATE; } ; + PAIR; NIL operation; PAIR}; diff --git a/tests_python/contracts_009/opcodes/utxo_read.tz b/tests_python/contracts_009/opcodes/utxo_read.tz new file mode 100644 index 0000000000000000000000000000000000000000..aec29b79730b71121b0c2b1b2e23a931c6173efd --- /dev/null +++ b/tests_python/contracts_009/opcodes/utxo_read.tz @@ -0,0 +1,9 @@ +parameter (pair (ticket nat) nat); +storage address; +code { CAR ; + UNPAIR ; + READ_TICKET ; DIP { DROP } ; UNPAIR ; DIP { UNPAIR } ; + DIIP { ASSERT_CMPEQ } ; + DIP { PUSH nat 42 ; ASSERT_CMPEQ } ; + NIL operation ; + PAIR } diff --git a/tests_python/contracts_009/opcodes/utxor.tz b/tests_python/contracts_009/opcodes/utxor.tz new file mode 100644 index 0000000000000000000000000000000000000000..81d9632d35d27230d60c288afe9461ed32c5a026 --- /dev/null +++ b/tests_python/contracts_009/opcodes/utxor.tz @@ -0,0 +1,24 @@ +parameter (pair address address); +storage nat; +code { UNPAIR ; DIP { DUP } ; + SWAP ; + PUSH nat 5 ; SWAP ; + TICKET ; + PUSH nat 2 ; PUSH nat 3 ; PAIR ; + SWAP ; + SPLIT_TICKET ; + ASSERT_SOME ; + UNPAIR ; + DIP { DIP { DUP ; CAR ; + CONTRACT (pair (ticket nat) nat) ; ASSERT_SOME ; + PUSH mutez 0 } ; + PUSH nat 2 ; SWAP ; PAIR ; } ; + DIP { TRANSFER_TOKENS } ; + SWAP ; + DIP { DIP { CDR ; + CONTRACT (pair (ticket nat) nat) ; ASSERT_SOME ; + PUSH mutez 0 } ; + PUSH nat 3 ; SWAP ; PAIR ; } ; + DIP { TRANSFER_TOKENS } ; + NIL operation ; SWAP ; CONS ; SWAP ; CONS ; + PAIR } diff --git a/tests_python/contracts_009/opcodes/voting_power.tz b/tests_python/contracts_009/opcodes/voting_power.tz new file mode 100644 index 0000000000000000000000000000000000000000..741bb196788d03e43621822dc4fe389ea8f7939b --- /dev/null +++ b/tests_python/contracts_009/opcodes/voting_power.tz @@ -0,0 +1,7 @@ +parameter key; # A public key +storage (pair nat nat); +code { CAR; + HASH_KEY; VOTING_POWER; # Get the number of rolls for the key + DIP { TOTAL_VOTING_POWER }; # Get the total number of rolls + PAIR; + NIL operation; PAIR; }; diff --git a/tests_python/contracts_009/opcodes/xor.tz b/tests_python/contracts_009/opcodes/xor.tz new file mode 100644 index 0000000000000000000000000000000000000000..557eaa642b9a2a8b53857ed7ef529e3fefc58d23 --- /dev/null +++ b/tests_python/contracts_009/opcodes/xor.tz @@ -0,0 +1,13 @@ +parameter (or (pair bool bool) (pair nat nat)); +storage (option (or bool nat)); +code { + CAR; + IF_LEFT + { + UNPAIR; XOR; LEFT nat + } + { + UNPAIR; XOR; RIGHT bool + } ; + SOME; NIL operation ; PAIR + } diff --git a/tests_python/tests_009/__init__.py b/tests_python/tests_009/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize.out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize.out new file mode 100644 index 0000000000000000000000000000000000000000..eb5c8f13a1d6b1dd00e27fddd2de216995b0dc0c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize.out @@ -0,0 +1,8 @@ +tests_009/test_contract.py::TestNormalize::test_normalize + +{ Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } +{ Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } +{ { 0 ; 3 ; 6 ; 9 } ; { 1 ; 4 ; 7 ; 10 } ; { 2 ; 5 ; 8 ; 11 } } +{ Pair 0 (Pair 3 (Pair 6 9)) ; + Pair 1 (Pair 4 (Pair 7 10)) ; + Pair 2 (Pair 5 (Pair 8 11)) } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_legacy_flag.out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_legacy_flag.out new file mode 100644 index 0000000000000000000000000000000000000000..6cdd983ac8030ba0159c9a2dcd0dcf2a2af10525 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_legacy_flag.out @@ -0,0 +1,8 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_legacy_flag + +{ Elt 0 1 } +At (unshown) location 0, value { Elt %a 0 1 } +is invalid for type map nat nat. +At (unshown) location 1, unexpected annotation. +Fatal error: + ill-typed data expression diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[None].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[None].out new file mode 100644 index 0000000000000000000000000000000000000000..0777943fd916ebfa6769adb576108efbee188950 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[None].out @@ -0,0 +1,10 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_script[None] + +{ parameter unit ; + storage unit ; + code { PUSH (list (pair nat nat nat nat)) + { Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } ; + DROP 2 ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[Optimized].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[Optimized].out new file mode 100644 index 0000000000000000000000000000000000000000..b56d1340b9b5e5741f34b1f7f9b56650bd3042be --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[Optimized].out @@ -0,0 +1,10 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_script[Optimized] + +{ parameter unit ; + storage unit ; + code { PUSH (list (pair nat nat nat nat)) + { { 0 ; 3 ; 6 ; 9 } ; { 1 ; 4 ; 7 ; 10 } ; { 2 ; 5 ; 8 ; 11 } } ; + DROP 2 ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[Optimized_legacy].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[Optimized_legacy].out new file mode 100644 index 0000000000000000000000000000000000000000..51de510a5cb0ac67964c69c8e1bd6549a96e1c04 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[Optimized_legacy].out @@ -0,0 +1,12 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_script[Optimized_legacy] + +{ parameter unit ; + storage unit ; + code { PUSH (list (pair nat nat nat nat)) + { Pair 0 (Pair 3 (Pair 6 9)) ; + Pair 1 (Pair 4 (Pair 7 10)) ; + Pair 2 (Pair 5 (Pair 8 11)) } ; + DROP 2 ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[Readable].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[Readable].out new file mode 100644 index 0000000000000000000000000000000000000000..e7c6e03f78a59da5e97da6d9b3c9a643fa6968a0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_script[Readable].out @@ -0,0 +1,10 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_script[Readable] + +{ parameter unit ; + storage unit ; + code { PUSH (list (pair nat nat nat nat)) + { Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } ; + DROP 2 ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list (pair nat int bool bytes)].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list (pair nat int bool bytes)].out new file mode 100644 index 0000000000000000000000000000000000000000..ff14aa44265e7e012e8008598407b1d7528be31b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list (pair nat int bool bytes)].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_type[list (pair nat int bool bytes)] + +list (pair nat (pair int (pair bool bytes))) diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list (pair nat int bool)].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list (pair nat int bool)].out new file mode 100644 index 0000000000000000000000000000000000000000..55c80bba781fd317a89163da8e0c563ffafa05cb --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list (pair nat int bool)].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_type[list (pair nat int bool)] + +list (pair nat (pair int bool)) diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list (pair nat int)].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list (pair nat int)].out new file mode 100644 index 0000000000000000000000000000000000000000..702a307b079ec67f70e3425e85225ab0f2eb6fc6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list (pair nat int)].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_type[list (pair nat int)] + +list (pair nat int) diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list nat].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list nat].out new file mode 100644 index 0000000000000000000000000000000000000000..1db99868729e831cab98cad487ed542acb64516d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[list nat].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_type[list nat] + +list nat diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[nat].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[nat].out new file mode 100644 index 0000000000000000000000000000000000000000..3712fce8c1f9555daab2473016bb4e14dbec79ef --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[nat].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_type[nat] + +nat diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[pair nat int bool bytes].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[pair nat int bool bytes].out new file mode 100644 index 0000000000000000000000000000000000000000..5cc4a5535ec8e9dc3acb855b4e0c450f230475cf --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[pair nat int bool bytes].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_type[pair nat int bool bytes] + +pair nat (pair int (pair bool bytes)) diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[pair nat int bool].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[pair nat int bool].out new file mode 100644 index 0000000000000000000000000000000000000000..33f103122378373e1eec55c21adaff0b0b173479 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[pair nat int bool].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_type[pair nat int bool] + +pair nat (pair int bool) diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[pair nat int].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[pair nat int].out new file mode 100644 index 0000000000000000000000000000000000000000..6a73e0340774a01326a3622157877df498306dc1 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_type[pair nat int].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_type[pair nat int] + +pair nat int diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[None].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[None].out new file mode 100644 index 0000000000000000000000000000000000000000..008d836e45005eaaca3d249bc5a22738eab8267c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[None].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_unparsing_mode[None] + +{ Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[Optimized].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[Optimized].out new file mode 100644 index 0000000000000000000000000000000000000000..69c0f5e7ecd700e2425e1f9fedfd9a845f1cbde9 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[Optimized].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_unparsing_mode[Optimized] + +{ { 0 ; 3 ; 6 ; 9 } ; { 1 ; 4 ; 7 ; 10 } ; { 2 ; 5 ; 8 ; 11 } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[Optimized_legacy].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[Optimized_legacy].out new file mode 100644 index 0000000000000000000000000000000000000000..d7d83531f0a9c67b1f8e7e7c5a6de2c6be2a1b06 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[Optimized_legacy].out @@ -0,0 +1,5 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_unparsing_mode[Optimized_legacy] + +{ Pair 0 (Pair 3 (Pair 6 9)) ; + Pair 1 (Pair 4 (Pair 7 10)) ; + Pair 2 (Pair 5 (Pair 8 11)) } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[Readable].out b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[Readable].out new file mode 100644 index 0000000000000000000000000000000000000000..13f23cfb1d1248305bfd68e14870ffaf701e19c4 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestNormalize::test_normalize_unparsing_mode[Readable].out @@ -0,0 +1,3 @@ +tests_009/test_contract.py::TestNormalize::test_normalize_unparsing_mode[Readable] + +{ Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestSelfAddressTransfer::test_self_address_originate_receiver.out b/tests_python/tests_009/_regtest_outputs/test_contract.TestSelfAddressTransfer::test_self_address_originate_receiver.out new file mode 100644 index 0000000000000000000000000000000000000000..48295cefe3b2c7420d294d564a18c44db6f6f473 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestSelfAddressTransfer::test_self_address_originate_receiver.out @@ -0,0 +1,50 @@ +tests_009/test_contract.py::TestSelfAddressTransfer::test_self_address_originate_receiver + +Node is bootstrapped. +Estimated gas: 1781.962 units (will add 100 for safety) +Estimated storage: 340 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000499 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1882 + Storage limit: 360 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000499 + fees(the baker who will include this operation,0) ... +ꜩ0.000499 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ0 + Script: + { parameter (lambda unit address) ; + storage unit ; + code { UNPAIR ; + UNIT ; + EXEC ; + SELF_ADDRESS ; + ASSERT_CMPEQ ; + NIL operation ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 83 bytes + Paid storage size diff: 83 bytes + Consumed gas: 1781.962 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.02075 + [CONTRACT_HASH] ... -ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as self_address_receiver. +Injected block [BLOCK_HASH] +[ [], [], [], [ "[BLOCK_HASH]" ] ] diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestSelfAddressTransfer::test_self_address_originate_sender.out b/tests_python/tests_009/_regtest_outputs/test_contract.TestSelfAddressTransfer::test_self_address_originate_sender.out new file mode 100644 index 0000000000000000000000000000000000000000..0d9cd7c32841de0558fa3b79dc672ed590adbf09 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestSelfAddressTransfer::test_self_address_originate_sender.out @@ -0,0 +1,50 @@ +tests_009/test_contract.py::TestSelfAddressTransfer::test_self_address_originate_sender + +Node is bootstrapped. +Estimated gas: 1781.238 units (will add 100 for safety) +Estimated storage: 339 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000498 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1882 + Storage limit: 359 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000498 + fees(the baker who will include this operation,0) ... +ꜩ0.000498 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ0 + Script: + { parameter (contract (lambda unit address)) ; + storage unit ; + code { CAR ; + BALANCE ; + LAMBDA unit address { DROP ; SELF_ADDRESS } ; + TRANSFER_TOKENS ; + DIP { UNIT ; NIL operation } ; + CONS ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 82 bytes + Paid storage size diff: 82 bytes + Consumed gas: 1781.238 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0205 + [CONTRACT_HASH] ... -ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as self_address_sender. +Injected block [BLOCK_HASH] +[ [], [], [], [ "[BLOCK_HASH]" ] ] diff --git a/tests_python/tests_009/_regtest_outputs/test_contract.TestSelfAddressTransfer::test_send_self_address.out b/tests_python/tests_009/_regtest_outputs/test_contract.TestSelfAddressTransfer::test_send_self_address.out new file mode 100644 index 0000000000000000000000000000000000000000..088b92501e00496d7585ddfc5f3018f3bdbba0f7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract.TestSelfAddressTransfer::test_send_self_address.out @@ -0,0 +1,42 @@ +tests_009/test_contract.py::TestSelfAddressTransfer::test_send_self_address + +Node is bootstrapped. +Estimated gas: 6615.952 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000966 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 6716 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000966 + fees(the baker who will include this operation,0) ... +ꜩ0.000966 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 82 bytes + Consumed gas: 3945.464 + Internal operations: + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: { DROP ; SELF_ADDRESS } + This transaction was successfully applied + Updated storage: Unit + Storage size: 83 bytes + Consumed gas: 2670.488 + +Injected block [BLOCK_HASH] diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_one[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_one[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..5b35559e8a9a9fbc6ac6fc581b673e31fc17abd6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_one[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_one_one[Fr] + +storage + (Some 0x0200000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_one[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_one[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..82e2065625f7306a7c9cc74aeff849879aa62a83 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_one[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_one_one[G1] + +storage + (Some 0x0572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_one[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_one[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..8fc32c88d47f8188e6eebeb0a9b4ab01cbae0bef --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_one[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_one_one[G2] + +storage + (Some 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_random[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_random[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..673c4f3f4ea6000fd1e6ac38ca8fb6cb3e1cecc2 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_random[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_one_random[Fr] + +storage + (Some 0x660dec4a316a24f34cad26e886cb480da89c55113f5c1a2b6bfdaab82d737708) +emitted operations + +big_map diff + + +storage + (Some 0xa711c66e47a4f376a769f9accfd675dcc6a2b9ce09c0482923c19f8218f16849) +emitted operations + +big_map diff + + +storage + (Some 0x111a13c7d5feb5e8fe5b2c5550d3335c04737fcbeece373eabf07b1b1604bb3b) +emitted operations + +big_map diff + + +storage + (Some 0x366bf41ff7bd7828a3d206500267d5c888aa120292be0cd6399fe4b9db75625b) +emitted operations + +big_map diff + + +storage + (Some 0x86b8dc4aa73cccb08dd143980ec0a4f73c2067807b3b4f2ff96368cb5efd8d4e) +emitted operations + +big_map diff + + +storage + (Some 0x7b83a6a4c37d5536bebe96766b25195e32b69257f3dc2d1e6fcdd7144db0f80c) +emitted operations + +big_map diff + + +storage + (Some 0xac54d72aff4eb7b9acce60a61f8f2ca1a1a387557cd6df2e9fe690ce209eca63) +emitted operations + +big_map diff + + +storage + (Some 0x183b7f72e291320045c63ad9453dacada669ef605e72c708a8735ae2fa7f795d) +emitted operations + +big_map diff + + +storage + (Some 0xb82eba460eb5d8e64d597cca0278098e87f2e1bba06d0fe19f6da2075084c66f) +emitted operations + +big_map diff + + +storage + (Some 0xb87216f6813286cfabec830fa176f2aa127cc1b99b824d312bd8d239c2555d6e) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_random[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_random[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..711f5c02dca578b2bd91b9a5b7200aa4193dca0f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_random[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_one_random[G1] + +storage + (Some 0x058026aa05e53a8be99d756ad00d2f3577786eeb07abe3d0bb51a9c6c4786fa31579791ecca13a22e423a3ca2e1d8ae6049f0d41d63294fa63d9679c2dfda2ccc5263bdff7d8f404fb566e3a420fdf9bcc003cd33b7d4a46f1d9a1dd059c879f) +emitted operations + +big_map diff + + +storage + (Some 0x11613e266146d8bf256974bfd8bc7bcfc1aa33d1abb8407d5199c18c1d71bdc27c37bcc64a30f3e39ef8f04e521a099a029636513b15f1e71a7aa6042fff9d1d552c542caa5f302071504d524d511173027aa21ad9d1928dba8a201c9f24d9a3) +emitted operations + +big_map diff + + +storage + (Some 0x026fcea34d1a4c5125142dfa3b616086309cab49e60e548d95de658af4d9329c269dc132bd5d884617e8767600daeee90c6f5d25f3d63540f3b799d291e5df4a90244346ed780d5c9d3afa8f3c9a196e089fa4edc4a9806592e8561d626579e3) +emitted operations + +big_map diff + + +storage + (Some 0x0f048c8e56ad4ddbb3fe800e2667ecaa5683d33a2828c7f9341ed2708f83e1cc58484085399822f6af8f05e9761cb49f0ee1db03e81501d8982d1362518386e77fbcf240d9d4768187ab4727c6b4ede0057dbe0358f37dac17eb2eb395088a44) +emitted operations + +big_map diff + + +storage + (Some 0x114c27c6a72b3eb7bb0176261d670ce20a9cf90a52da5b68faf2013bac314f7987e735ac04ebb1c164a48f60c16ec4be0c1eb74c865b1df94202b4eceb42e22d86099ad360339303463d68c0d931774304fa4c780208abcf1c79640b0c4190ce) +emitted operations + +big_map diff + + +storage + (Some 0x054b5561e8d9de0052a167f4886efd49890dfda073843dee3077c37ccb3d7ad2326970eb9615f318a0851b30aaa7f1150b4a687ddf9672bdbcf159358ea75025adc8584532a046b48d30868ee38dba0ca8a209af29cd791594cfb7e9ae991119) +emitted operations + +big_map diff + + +storage + (Some 0x174e2a1898303aba4520148510fbdc740d8154886d04d1ef7f65c904cbd2171af98345f2463bf26c35576da1be372d680bd755d4c860640a9991cfe703590382c2c20ab7121bc94926dac025e25526ffbb234785bfb6eb5ebd9b8be521e5cda3) +emitted operations + +big_map diff + + +storage + (Some 0x04cf46cee905ad068310d3e0764cba786372efd7eea4a8a2354da24eea26af1578320cc25a5c0dd9fa016c16ef956b071529c2fe97c6c69690675a5484220900d6c48d03976289801f818899416e014e9d50ca19c165b9c43e4de8ee0b16a792) +emitted operations + +big_map diff + + +storage + (Some 0x0ec968f32f75a84a3bac57f2025ebcef650a8ccf5da9b27ca53331eda42ca2848948e8e9cc7588acdc9430ba4051a0c70ada591853bf90ebcd4df22ce469c453ce5d4bfb7d968ba8b85ec48188f7912a549dc7a81f246264da9b355aeb1b0178) +emitted operations + +big_map diff + + +storage + (Some 0x018637aff527610ee1a083eca3f3ad2a989dbcce2a393e24703e52e418b8d373433155bda3bb4664aef12d8cb058932d14d26d519045ce36b21cb50c77373077cced9fc000b8696cc5e035ad7d2dbdf41971c8403bee31ae0a6a36263066b847) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_random[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_random[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..7d454d4e98c472846169a095b8ef99de604d2a58 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_random[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_one_random[G2] + +storage + (Some 0x139bd98ba7fa37cb7e1ba9177ca818063bd14a8aba77a7f4dbff7a6c848683ac17415104d5c63e46df848499f209dfbc105f18d1e114210fbce28d22f30818e75bc412526a55f7937ac290bf37adadeee6f40b9614b74b1962376d5c3078085a02a53c9021eba8b107a43bdebaef9fddc6a8c8d8c19138d06a332f986f256c32b8f19d5e39f203eba23ea36b4bcff9300dad02b62de4defe358fe6b835b3d93571ef66989530e61090c3db145c389f66ab2ee01e4f05a9ca18fb1ecf48faed94) +emitted operations + +big_map diff + + +storage + (Some 0x192438792f58ae648d5cc73d07d263f0866430fa798d61cddcf35ac48533cd60ceb7e1adaf2ac7475b0819d583b5fe210454a94b83d8a110f699db4c1963dd9bbc1f5b8d1de6ae59f0c5c1d0c0fccdc04d5cfaf901b9c1b713b48938589bd53419a11025e8f61abf088d72b3fe3e3f8d6682e235804855d5a02897ad8ce252fb2584670c27dd81e48ba14d01b09add9e0857cd0cfd23bce8702ad2cf73709debce427df15ba1bd920c941eabc712fa2652e906a1f49d604222410929de6498a1) +emitted operations + +big_map diff + + +storage + (Some 0x14e9b22683a66543ec447b7aa76e4404424709728507581d0b3f60a8062c3f7c7d3365197c59f7c961fa9731084f5be60d0a936e93d556bdef2032cdcae2fa9902dcbe105e01d7ab7126d83486d882c4efd2fc1ac55044157333be19acf0cb7a10bc41c8081c9babd8d5b41b645badd4a679b3d4e1b3ea2c0e1f53b39c00b3889a40306c9b9ee2da5831e90148334d91016474d07e0f4e36d2d51b5ca11b633b9a940b9c126aebf4a2537c18fdc6967fb677824bfa902157e53cb499a021e57b) +emitted operations + +big_map diff + + +storage + (Some 0x139bf65acd684812defe34a647e77d562d16ec07aadc8df7460835bb42e52783265fc7062d24399533488aa26f177f300a05c44ba3deb272a9334bfbd15e3df49169622e8cc739c8d8ad1658769e94f28c36b3ddc608a71ea590f5d956820116019860de9ec8f5257791279a546c6d7efc62ce91114bcb11053f999f5adf35c0f0da321602ce11347567aefe05c58bfc17693d82a530ed5c07e7e1d87d3ac3c639005480f5fc9b9fb378aa693781d0ba8ee097bff01964faa41c9361ae9da3ed) +emitted operations + +big_map diff + + +storage + (Some 0x17df1d683296888e1ef6becb004061a658609faa7aecfc56e09be2cb07f621e6bf383f3ed9eaa5ad6eb4c5ff3e4ac51615cf8e6d23843b1665d6efefdc8024b15651ee05b939f1fc529a5d4233d58ee83cd4fcd07508eb0fa1229bf649db9fb407167c5d410f1f4c403bd4cc234e3f757d74587ead39d549b88e6d6e0e187498386152a981e26a0ecfbc89349db5e5f502e61c367aea8d829cbc8d2441362f075c9245a82c8daf849dde2316fb06127db9eeb2d99a5bfee90e39ac18ac062db2) +emitted operations + +big_map diff + + +storage + (Some 0x072666f55bcd0330329524efb1a8bf981fcb0ee73c739be4b83339fa2953888bf058a115c834ed7460f6ef6e7aa36d0d1002adc9e373cfcfc62f47a6a6670700c749e6df92e360fa0a379c5621b39f35b02c578aea5e79d54f692d2fab9ad7c01527640d6462324d6a137bf7c36abd863f3efe2953d3b1729e8d3f07321af14f38893ca2e61eba4c987a5f7988569c4f0626e86728ce9292df1bd38c5e21b32d329b86f8f41eaa11eac36cc0ddf0b3fba543d94f4d3a4b992eb7e60fe9680072) +emitted operations + +big_map diff + + +storage + (Some 0x152f2b940efd3d2c53640e2ccf881935f114404ac116a54c859c59511058db4d7e2f4369e3e846ccdda94e72e22e06ce0fb52ada3931bb686d52e45ef020b58b9da28f370cd27a595b07eae78ec26e044f58c15cd256fb426e0b862a37bb751212256f5e61ef53dcf799657d5071e6dfa1040b2ac0ec31e18069d2e6e7e6424d09ece1b68a8be6d56dca3de4d467e8a80c395cd9ebe4645d3e465f0263bc100bb9d49dbaadf0572836c8bf03d8c2155068a1f56017864a51e8f4915d24885afa) +emitted operations + +big_map diff + + +storage + (Some 0x0c5ae8a5d7042b893b4600512b81b205b0f3aec3b00d0b2ece549e31c0466f49cd8900270ac48f253e66dc8a05a83e3c0ed8790344651fb0d17ef0c0f86340687e890424c06b5426e6732c3ff837ad4c76a2dfb9f5d80e80eadd024cc4c386f10bc203d5bba633fa3f50fb84140e9ef8c0f7c83ad41b2d1230b8af982e541c07f137b59b71142a4e2be49d9a0fd1212f11fe2ebabe025ab38dfc64f38e724edea44610b88239679e60d9ee151174a3bd1425eb865b8533c0b833577e430ae37a) +emitted operations + +big_map diff + + +storage + (Some 0x127093c56626b5e31114ddc6565ac257c3f5642d4eeabb469c2e6cfa23c713bd87fbccc738eae6c6356eb1bc3e62babc1985437cd7bcf96041d3547efa5c1c5ab0dc66aecae18f5a70055a4f4c518b6f7f31f18709d0a7f37f5eb3cd413557f7164ead5569fd618dee7145ce3b5786a4d5551c63b6936e682e618f9db2aa1c97117369cde387255d063890b4a7c788b80ebabf2427faab4c8cc0a71d467ca7c78cc625fd9dbb48fd485124cdf1c5748f6488a06f1e71b429fc904f249fd5885f) +emitted operations + +big_map diff + + +storage + (Some 0x0e18a45de8e16ce54070d9df1ee055e933e7c65e2d33bbfd9eba62dbcd84c00eca86bffec4f0e02ea6172242243ca205067af2bd83fee2481e6ed3fee5b327e9d7aa95513d1fa3b60093b86b29ae14df53b03ac63f5b0c2ea3df9575fddd2bc7045df4179eb4de582fd6c3955d1947036131eea418e57fa977181e9b7c6af89686f47593bc3e1d9ea0be7c46004f23ce0d3abe0bd9fbae591d5b3fba5ed26ee6756ab595e79f27825afe20fa68d7d6b954356b589c80dc909d5d91c6afed0440) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_zero[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_zero[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..e4ebbadc11c488d1bd5a53db7aaecb6209e26c5c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_zero[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_one_zero[Fr] + +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_zero[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_zero[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..3c698e2b9aed751cabe48e732d2a76149611fb65 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_zero[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_one_zero[G1] + +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_zero[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_zero[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..8422512751dde3c91813b63fa56bb902790c2c88 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_one_zero[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_one_zero[G2] + +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_one[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_one[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..6e3eb021686f26bfbb59231d2cf90e3175e8d7b7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_one[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_random_one[Fr] + +storage + (Some 0xf09d35856fcfe3dd435bed02f67e1a34b246f9eb48f9034e3bce2a83ba806c23) +emitted operations + +big_map diff + + +storage + (Some 0x2a5cababf8f15f832f44e2a935f029722c2e4c87fdcd3ad1bf4ec872042d9f11) +emitted operations + +big_map diff + + +storage + (Some 0x90bdbed3c04f5a16f7dd885aa2bf82e0688da08f687d29a38c6ebf46631d7a38) +emitted operations + +big_map diff + + +storage + (Some 0xb0df3414f8f1b9b0265f7d243790b57dbf3f028bd0e99707a4ec7c6753ff9c5a) +emitted operations + +big_map diff + + +storage + (Some 0xd908b12f4af05efc5a4fc60806a64be2cc267846d93f2d6e857334c2aa66dd62) +emitted operations + +big_map diff + + +storage + (Some 0xb2a92200b1c95da0fbc293e7fb078961820240c26c87ff727a63fbcd3bf7591a) +emitted operations + +big_map diff + + +storage + (Some 0xa4fcd4658ae7312cd766f6d32afb2a57acbc386000d7a817fb45b4ddb7064c5f) +emitted operations + +big_map diff + + +storage + (Some 0x93e781ac13e039a74b9329fe4c62581e78cbe5f98c3a40ef4aef0afffb52e915) +emitted operations + +big_map diff + + +storage + (Some 0x4c7dc9dffae7cafafb2d713f334576a96a530ed57c5fe4c083130f67cce8c33b) +emitted operations + +big_map diff + + +storage + (Some 0x2a72fa0e849cecab222419ae6b7ef22b21221f06f7755caab4aa0c035d10d90e) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_one[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_one[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..bb5e71c58c3659f929a3d466aa20fb7cb0b1d730 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_one[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_random_one[G1] + +storage + (Some 0x03511648ff12b05121af6aee879ec39ded8e895f3bf83c64425c374ed1f1eb022d69b23657d36c7caf3a4680c0ac4617193583c1f57a61b18d61b2584a9b373bb45564b67ebdb884f7fc771ee639d596d343b302872a39a649b25eb4420963af) +emitted operations + +big_map diff + + +storage + (Some 0x01382fcd60894365df78f25e41a72e66a8b82633a94c8aad9a782bf880951b2e77794775bc0f2beb2200896c3042f24219fbc49d8c9f4a446ef1e5d3c8bf0d5da5e5c7480389030f971eef2fe382ecf7017351d7a838456e9f32fc7c32400277) +emitted operations + +big_map diff + + +storage + (Some 0x046dfb65aeebf558d612af9e6efe5aca9332026c0bf584afe7f11166a511a209cb750b2a037f28c476d49c0f8d5b42401479f06b06eddadef2139b142d1f44d4d63ec870a12fd574a89fefb05000a48a0c1d4cad1ec1fb53ffecbb05d2fd1a26) +emitted operations + +big_map diff + + +storage + (Some 0x12f06982de9983d040b51bf0cbbca5c8eebd6636f81c49a4b56d06ef8092126c50a0451931917a5ae0a551b16d0e3fa60bab06dbd78fc6a64f6c9647ae4ea534baf2fa5f08d438399937e4458563f47c1e8c4f0495d5c0f6609492d548310cb5) +emitted operations + +big_map diff + + +storage + (Some 0x0d8b71b72b170030fcb76bc7324fa823f8b59f2cb6b014687620a3d01c8cae25a41c423ff9258524571ab273fdd1783704b9fd0d5a4e1801cfb819aff9297579012d3cf77291ad1a2748fb1727c46fe3d0f9d2feadcc57c2cd495b6cb9314a5a) +emitted operations + +big_map diff + + +storage + (Some 0x016a3c5fff7923ad1c3566886a6dd256e32e69d992fd92a34496ae3667b33df6b699b7805fe732c68c98703e93a2ab9716dcf3d2a244889d3ff2804b9aa2043e7b07398789e39b8ac022606a90f303f176dca030856cc0777c2df1f7fe1a58f3) +emitted operations + +big_map diff + + +storage + (Some 0x11851bdd68f0062a6f4729647cc25af2431689ef7bddd79f82a4682d6d1292fcd7922a697a4fb8982d26680ad4af336004af74b34bdb318d0fdae9d0413065d47a5202903a59cb033460b3d88b942e5f611d542fd2e8b9c9d300b3b153f43efb) +emitted operations + +big_map diff + + +storage + (Some 0x07809251bc1b99439e63008e8d783acbe2fde93625f4175c33db220d96c310931753794535e47d84317de54b035582e9060a1f49de845f3f870a46e7e8939bf2d387f2e6d87f2244cb26b9e153723629d92adaa94f46e1be7458fc45c556fb0c) +emitted operations + +big_map diff + + +storage + (Some 0x0ce4e3355f0a5df9eab02eecb2510de9a9837611481d4fe8e5f803e7c60db5da63a1afb13a019a0f1f199d0ffe87297c01d5cbae9a4df48cef28ab34c8e2a684b1601fe30729e2512e937eea6e4071fb715926508fe1efaa9edf0633a1057718) +emitted operations + +big_map diff + + +storage + (Some 0x1358174de7b56cf42eb7d6ffe1ed41fefed8bacb3b18c88925e69ec8c51992ff84942d2d468d49e256d77c5d38d9d71b016480cb05ae9ed0c549b8446e9366493ceffc9471c206a359d8c9f58351ee2f6292208442baa3cfd09813af73d0b7c7) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_one[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_one[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..85a9972244e3cc25de1904473fbe27851c0017d0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_one[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_random_one[G2] + +storage + (Some 0x08fefb71e4511ed0d6a3bd0409725b908a0c192d13307a72b1c83e586f534897e3d2a7276eddf2c0027b44058e5da8e11911a8bae300eba2295ae0121dd9f78d2dbb3fa6f38f397b8b67dfb43d1c7303e699925597f04c463c55e625b66d0c02107220b0a6af8b1c2f445c396e3920a573e573b90d51d0d7e3baeb7921f35a261a1324fa74cb05cfc5dc3b09c14ea2fb14e0c74a54dd945b8256a69e2f72c084e54e29ba8b0dcaae61f8dded3054c47d0e96eee36c0bb002d2803f7b51cfb96f) +emitted operations + +big_map diff + + +storage + (Some 0x0508c45054a19a896a24fc4cd6f35ff97a3db9375bcd489f2737f4182c6f7dfbbb7412497f3609d417e44934c4ac10b717c67161445629d6d7532e40929c795b8b3d672a053cb59408352c24d5148e97e807dfbca83a3fa49a629b4a00a5a79c0f2f871ff459bfe82b647c864560019a5894f7b0725917bded14f81631f4df52cb88e0d72fb0503d90a562f7b28f49cb00ecf93cf750fb701e2e3fb50a7f1ddb205562a0c84097c241a0491785a8080fcb0340842eb81908a282343ca94c6d38) +emitted operations + +big_map diff + + +storage + (Some 0x128b9b6b5677981632671b3a4200b33265fe75ac2569fd7613357b59dd740e2abb342cd40c3f7021972c2b85a4cc9f680f7e28d1c48fe5bd039569424c63eb9606e7199bcbaf81d3b45ecaee9f469a2278ce9b933961384a21cc547facaa61cc03b6424ecc1f5d20cbec956c93024ed9153c2c3862fdcbcaac5cd2e13806f6ae2ca4d3253b7f712b54c879e26dbf3e5807f58735263798c2c6bc07be9012e4eb586d64021ce5a0ad7ec6dac72224f7a121f2630f07a49e4ad438e359b72c16c8) +emitted operations + +big_map diff + + +storage + (Some 0x040323c862873989f4eb7aedcd6cf03d9c4e6d89fe86ab05767f3b10b988fd452383160f11559ec04b6ad10fab6765fa07416b61c915c55945811dec59808a3640b58243bcdf79cc7d8c5c7b4769118e86fbb5cd9296b6ea8b1009b309f33f6619c20ac87938bd643e0d8fe7f41a2f7fb89987340cc557beb9c499b7ae0beb651d13a16b55fed41e98e8118495d570e3165305df86cd00ab6b884471b0c89c2099731f613bdf07fa5b453fe47edf688b7e340f24aadef705903b4c0abe322a90) +emitted operations + +big_map diff + + +storage + (Some 0x05c66c2a9cd7bff629a8be6b6915f8cbd5b9b50430ad9f1f95ef83df93a289b14b0c069a45e9a3083c8091222e3f44e30b3ed9b7fbec7939db06aad0d5140c7c4933840deb9a514e568e2efa86a4ba835752a6ca91359f8dc20ac43f3fb30a3c04f8c1d1e302d37a0ddf2f4cbef9cc2b317ff16dd818725cb0d0195974992b14ee683afa06101db2acc697ac3f4202ef126995a62e8ae1dff6298dc9f768ab5a183d3a00cc56c81bcf3ab05c17087e66e743d559a4707b23c4b33f484aed3848) +emitted operations + +big_map diff + + +storage + (Some 0x03c9200acd88aa776039333734833f04c3673ef47f8e39ef44a98489a3683f6eb75032a6a5e134adab3b0c06931f444c10c4302c59f70893d23492c5ab767a6f60bc5521aa4ae879706b992726ce64cda1187e26ae2fd0cb3d05fcfa3e8f379902765404f27b2d4b0e22b20cc86a9ab7f0cd3f3f13fb6863ff9d4f26860c3905341d1a267a738e4385270f746afc93260fb6b00fe51f9a34c77e18e99d2c6e21c653eb82450e5bfb2d0d9a40d5e45696a1e1b4e32ea747f1e87500177b67e37c) +emitted operations + +big_map diff + + +storage + (Some 0x0cf8aec4898b6cf6698e74551deb9aac87a11dab50c7a3cbc69b2c4b4b230e9cab2290f2135fc365a6ed4dfaae5504821866a9bc35f182f2bc41a5bc2e4b998385e157bb9b7aab5b3722aa145b45681c85318f45a754c6c324b8ed3be1519ac013f476059991edef5732f11ccef162d314a7eae6aa22d8ab1d63a9d7207bbf3eb73021dc2f3562a7c69326de49e44470106e5429bda1ad096008838511176e879d4902b41cad20ac87bbc36c0d79d424e2a396893566cedfff341354fe901619) +emitted operations + +big_map diff + + +storage + (Some 0x0b9da9500e096383beb19b243b5d02ce37649b33f4e1671d649d8804552882fc1eee23f9fd522b022cabb4c962f73f0208e73a90df86cfcada188576f7f9d0a68b274aa0686402cd6b9af6fa0077d090c7d876faa1ff8222d00a8cd137ba02d31751a64a107ff326767085a8e486c60b604fa734c79935604869499ca2c5a79a8d37fc453c48cd18406e1486b7169445020494338e65c0db9bc80313cd0c4f8bb0c3d797e2a043652d5ee3a13e9ec97b6caa76b139d9e0ca05dcce3318a0ac4f) +emitted operations + +big_map diff + + +storage + (Some 0x091a244f18b87030e2b863c4229cb5e1afe53134e8a49ef8381da6f9a6816bd811cc485d0d9f4af8e702d2473367facc10c88b308cd546cb4f17a41ecf063b1326771b8b06099c402d787fde9f0cc13e837ca584134f725fc4d257ae04aa791d1100b618548b45488a0a0c52831f0f6252d805cc24118a8077d3985011d9afd8524d0dc630fd9c9279187251aa699bb308c895051974015232739452ad614031630ec533cae1f874210d39fda10a3cc34816075703b6e1c7f2902c6afad0518e) +emitted operations + +big_map diff + + +storage + (Some 0x1401fb979d3d7ba9f9b7464c12cc4b299242008ae161e00bccc6d791f8c6c69475eced6fd21f854e1f10e479af46730d08f0ce149b481d41e0862e195794d641337be00ad3ddc17eed2a107d6b20c8abfd109e0f75416f8d03059aa54e1b5c31170a0511c66e5557226619e6d0ddeb786b77fbc2a0e4125d37ed956db6f8eff7238e326d4dfe859f452b9082c21be1c60aec585dc2296b6ba5c10d91ab8235cfa1aa64f11bd5bab8bd9d929e6d0d86e8ce126617376551bc613366fd6e4ded1a) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_random[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_random[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..23b412ef7355f2b46734074ec0bbb9df8bd9b7de --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_random[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_random_random[Fr] + +storage + (Some 0x32c59df1aa60931c6fa6ff2b2d3358ebb570cc673b3519afec797a9a4dfd7427) +emitted operations + +big_map diff + + +storage + (Some 0xf2bff685b56f9e6f601d6a12abdf82db11d0ddf088620f605f873edacd48213f) +emitted operations + +big_map diff + + +storage + (Some 0x49c26f616a9483bbcfa389d8cf7fbe992621180d464407e757114a0804103f1b) +emitted operations + +big_map diff + + +storage + (Some 0x522f644c7566b3ad9445a0ac25b904b76c72434093ac409435d135f6e88e1431) +emitted operations + +big_map diff + + +storage + (Some 0x9efb69b24f277cbd42e5631c2e0ca566bfdaa9d27aa9608741b691fa01ce913e) +emitted operations + +big_map diff + + +storage + (Some 0xf0a71c2682cf211a1c325c530d0505eadc8a18974dffa4619e9b191050540c68) +emitted operations + +big_map diff + + +storage + (Some 0x4b18e93c841b6e6145923e527fd4fc35d6dbd6efba45745dd040a212a93d2d6f) +emitted operations + +big_map diff + + +storage + (Some 0x0918faba389d8ffb1b18345d62186f0980efd1724b792a9fa84e037513b4b165) +emitted operations + +big_map diff + + +storage + (Some 0x9806b79c2d171acc44814af407331430dc012ee27c5e52ae4660e8a3ea967242) +emitted operations + +big_map diff + + +storage + (Some 0xbeb8fa12abe52ffa9fa48d73d3c176a0bc3f8be04586f86dd456e3049dee0428) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_random[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_random[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..c7e880d1da8c210b4b09853a3ce7b4a4b53fb6d1 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_random[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_random_random[G1] + +storage + (Some 0x0572db5547103186bdf2f89953627c1c6ee79da42909470ccdb2b3a63d1a56872fa3f3998a53af08e34f6cbbb5d2ae31134939f276ca6eed853a730194aec002dcda3bb02231e12852a23d52665bbb4fd4c9ca2060976768f294e3a651bdfa24) +emitted operations + +big_map diff + + +storage + (Some 0x19bf076ad1697fb06e3006ba85b7299a58da677178781306ed64bfec71f97195e0fe8e5bbf9bf9f130c27fac85cf0ae102f80edcfe8374130006f99a0415e7debe4e2452084af7a92ec6b32a3c23acb1e936098bde4e99ae33d5bd4f098189a5) +emitted operations + +big_map diff + + +storage + (Some 0x0f8a8b4f0e2bf9e5612e906f9dee13de3a4a86a78779579ae0931938c9e33fabc200051dca4c290d3cda64c46c22d65102bbde334d33cc4d9b77b220848ca969b86a4d3fc828ebff8c154f8606a99fdb6c12f8e3a936b7f717307ac66617c155) +emitted operations + +big_map diff + + +storage + (Some 0x168ff86947fb37c511c29b34cd5683045eae063d394d4ca6fb478be51fd0d51f02362afa2e5b829e161744b0cb44537009da2ef5522ecaca11925bbca35be447402f2385fdb000647b0f97fd957706ad54a89dccc9d91a967fd7d3245699ce9a) +emitted operations + +big_map diff + + +storage + (Some 0x132714e690347a4818aa28078c04a9fa00af5a874f6e384b3c10385edff00b078fdd9b2d24756216cd221fcea02836061565f5e4903c19654928de543888be273f11954cfa069ee8b7b28f1501d723b5cd53a070c99976789683a9ba84ec3f88) +emitted operations + +big_map diff + + +storage + (Some 0x1160d2c1a9468460987e83389d2b14e83da2203bccda6af5698088fba85a70b0f81338e7266f1d2aa35c0c9fd90849cb19271f959b22d25e9d39be01e81ca28cbfd941681141e8494cc53eebf0fed66cf1d9c25cff0acb79a9c8de89978d665c) +emitted operations + +big_map diff + + +storage + (Some 0x19e4f619ba2bed08319d9c6d8233ac67992f979a09c1c2b578f6db33160da265453b6534404273f58b62b465081f177a04b2b5742855d0273a9a4b285040d806ac3c9b4222967dda1ca5b15b701e1cd8ea6d903ba3de1d4b772edd312f5f0e4e) +emitted operations + +big_map diff + + +storage + (Some 0x11cdd047200409941c0c76b6d3bcbd8e213190b4a0129a7bca64383d7574b41465771ecf903dec7f572dd4363595be400ca671f579f590ce3014426b45cf4ad91eaab36cc69b4d594dd60c3521ef037eeb4ecacc4449aa71f26f434e35a87746) +emitted operations + +big_map diff + + +storage + (Some 0x00b2274f474533ac0db515a0e9dfaa821f5da4d22602adc3b63757e0258b237710273f0385067c920250f3ac93e58c5106501678f78b7248129687c46e47737e9737cb4b57bd37495b2966b61239e5fe91946d65c19f948d89a2905f23ba4b33) +emitted operations + +big_map diff + + +storage + (Some 0x02469c3272ed5ff2685c19feeb227f6ac7fd45eef79266e78dc17bc53930ba5b754f94ee6f07c28a0be5f7cd63ba616c0cde39bbdb8e3add322a8d0ced1627e2601442dad06a7b1c0fd9ba9e08bca8866913f0336de0075564dad5ecc63c6cc7) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_random[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_random[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..03e1f2fda183d7230aadc8646f2bbdfc1d0e7e8f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_random[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_random_random[G2] + +storage + (Some 0x14e6a70d1e489c9feeefc7314994b0207da500737728cc2cd17919ed6d5eae570622815ee576563c25075fad12129e900b9764ef6332c435e56a57c1a46b1c427889456fbc01b6e571ea995e925337e6cdff2d062520c61c52d2377e773ba34e08bc7961bb8618eb9951954ca98d01eb69e56e04d16b7a2c21d8cb74ed0bcef735fdc43e6939c4d4194958ac1d5f70d41407d01b8bf34478d970a86af954f0ec67bad1a95c43ea118b8ae2e9ad7053cfd92b0058755e4dc1128e4e17476a8653) +emitted operations + +big_map diff + + +storage + (Some 0x071616c0847497f2acd699cdfa848cd50527971ba6d99ab2debfaad23f658f233c262e78e4f841e4e24b16a981b46f5b13b2de1c75de619374ce4715cda6598b7603c474f4bfae3201e26ec1a0ea4dcac5bb859067aa907fd113cbb8e12eaba0099bc61dfcb137a7978464d2c4c2db5eea9dc673857ad8dbacaf8a30156c2495bb0f09dc5e6b66c9b9a5245a5dd99afe0e9f735ed6682f0d92af05b3f965697c1e8f4ee5aea15caaa6e6905db608aa78c788554f1d63bf1781322ca089a73226) +emitted operations + +big_map diff + + +storage + (Some 0x0bcb3473d903308ecbf86e3d7339f636944b30ae69b693ee870ce4313dc5c678a8e3efc782df3c143200fc9f9c74da9805e4d15ec9fd45471f05f6a89c234b4bb353f5f0b59ff1c32aa0a53e3cb5d00d2f1a4bbeb26df8feafc8c6eadd4271ee0a479169a73291553225df03876a1cf264fe9fec6c1d7abb9498b6e9fe6f68373dfb11c897c8f4587bb68a73348624dc114b4430ca48f9e93c2ffdba64d0200b6213aa1c30dc5b8ee1ada58f7d8f17209c80a0638dac2d84706bb964d5adc810) +emitted operations + +big_map diff + + +storage + (Some 0x02bfcc6cedc5432b3094b3c3a07f4f5605e396779c996fc4451a148626994422aaa2813f25e971377cf4a79199e6b64c08dfd812339542c370ab0968994699fe11be923f5ffdfafc489e92f00aa3e7b346c15a216f4756318f2e275c1add44b1184926b94b03ff641a4dd7c48a62a8bc95db0e10051542e64838e919936b1dedb53eff5aff762504b52e7d7f29038b9807052c826bb33a2a63a23d97f1ae4631b78597169d5a8c5c7b44e76a9612b4caf931cb991bc50c400ca2dae41fd284bb) +emitted operations + +big_map diff + + +storage + (Some 0x199dae008159f71a8766dc2dd36b38eea3cc4570f53c5a75e1c634104c2de1fae8d08d82d746a32620f9fe735e1167c20dc0f1f29d8cb8c7003a0134003fd6bedbf06e3ca40163ade57d7c58134ccd178132839a421a0c54e4e3d7f1f7f6f3c302b2e86c3571aa93f060ac296490439624e0a65c3793ca193d12a87dd59d9db0ded93cb48dd1bdf2c253d512fa8740d40c60c89c6f6f3d0a1e031e9cb792c42988c5fd2df05221d44f0b98db56fcd3fce8dc52f7aac73e65da92a97edd38b871) +emitted operations + +big_map diff + + +storage + (Some 0x057b2871d7a164fd1ff36b65aa26203e9ead4073db80fd3e65cb11f526c3a36d04fd5d42d77f2eaf8ecbd87d31860ac60702affc28f09199509f4bcafcafc555e2924dc7023af9663d5e2add1febb92f274f7712bd50773cb3c21e058e06842911a67737914abdeb318d01a4dce9de50cff14a385c919d69f2b6dc9a4fbab82e4bc73ff153379aa09f44c9237c28a97b194536cf4ef1d033722ee02f2da4fdd2c22c6aa5876eb5e4632f57b86c9a5b1a750a6ce6eb38a21c9ebbad3477cc5081) +emitted operations + +big_map diff + + +storage + (Some 0x0f560f66aa318954f1a715277e07586e66ad90e4cae0e3cdd99a927c59cf9dd4fba60a1ab352ce417440e078116f8d4e06102984b8bcad27f90712873b678249ee83a01a30b0a8feacfa2bb4b068fa0f0342ad55bd269bdbebe7c5cfd5769098084ea794e5252f7cf5b0fd10db3a17f5fef9c3df9418109b9a269790dc35ab83821d39cd373dd26a60fcac49f57f1372111b5f5e8bfc1c2c921545561a541a1fd6f3e7b5dab870c16ffa8c41a8d1cc91d148f99700e3968e0cbff2f74b4613e9) +emitted operations + +big_map diff + + +storage + (Some 0x12d73c3ffbbb0e5135c89aed8a0bb246ac94ba2ffb79fdf103a7c9e71bf09b67fc928fef16c4013b45b963bad15e0e020c0635fb75638ffe385e578e06098e1ea4e5697a3850fc31f888c7ffc8544c4322ab5fda30c34b6959636ce6db02998b03c35b506840723cc3bc4788c47e64ad00ccf727581c76898bf1b331860ead87f9984965c6ec515f0b2ea1bc1a1aad1a0e9c8bc1799a1777a8acda5dc68ae83f7200ad998be79c35f252aa1e427c0b51c9fb463665acb7e7678797a0e0677659) +emitted operations + +big_map diff + + +storage + (Some 0x12f203deaa2a60bb330227161f38c0104c92c1598751bae6af52102dbbd6c9c4d2ec72155b9b4363d90ec83dc7f9a23a0fca208610b342d53abf1d5729ae6e39806844a6eef99c0df4bfe6eaa8b1216c0dc9e4d9f6c4d1f7f8a323459aabcc78184bf83ce121264be8e3931e50275dccfeb4318b1d6a834fd3e5df9b0f33748ce3e88da3bee4f3111f3c0787ac93891c073e576342224498c6c3fd5055bb3c33a8165c56dc6829261511b573401e707e055f9e43b1f29307ffb9959fb114162d) +emitted operations + +big_map diff + + +storage + (Some 0x1636bb0aa543964f7b8b5eb9c79a168f4840befc80a40b98716f5be1c85587c87d541df53c5344fc43fd59e7bef0192e149733e479d7e718938a4da503972a834f9e2b725430a3349f1d8359add70c286d912d26afdf0bf9ef72290cce771c9e11bd93d75a681fac52f10efe82c86b2a6e08a154ccdf56ab2af2c199dc9519ed94bc7aea2b2afec5cba663652bc8906c02c0a16e0c8d7ccc739dd4e0939dd5438ee244b52cc7cc22b3711c5738ee6a110442a7a75e8c5324b2e0a2c9ec61c475) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_zero[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_zero[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..b0c8129ae44ca23764d8d6204b112ef5b97532da --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_zero[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_random_zero[Fr] + +storage + (Some 0xa739fa15d114468388738a042a2d5c1697ae01687088c0f12b1a9aa08e8d333b) +emitted operations + +big_map diff + + +storage + (Some 0x90d72fcd8feff9474e2e54b4b9dd25693f4165bbd63e9fb1df790005841cd138) +emitted operations + +big_map diff + + +storage + (Some 0x1d88e731f9ace2515da1c8a180a91edc5a582ed1c55d4cfd32eec3124afe754c) +emitted operations + +big_map diff + + +storage + (Some 0x239754a5133c74f2cd2e055471a52aad9bf61d0cb8d87c1a145e52fa4b623471) +emitted operations + +big_map diff + + +storage + (Some 0xd96f5c434bc636ac77a076276cf41025130b480175d4ac3b89b492fe8ce02a59) +emitted operations + +big_map diff + + +storage + (Some 0x55da36ff0ab31698692128f58826a17fe737a5de292b3833f84f6b2dc088be48) +emitted operations + +big_map diff + + +storage + (Some 0x8aaac27a92aca48439a67deb4f7d04a291eaf8df409a966a5cc5938a433c8e46) +emitted operations + +big_map diff + + +storage + (Some 0x75c6cc6c226ce12140160f0740499913a5c2c4788868273b15dca2bd7a6b6837) +emitted operations + +big_map diff + + +storage + (Some 0x800a55193f60eb4de95f6c29ab095ac4f3f1d21a1e90096eba89c4c00f2d8a31) +emitted operations + +big_map diff + + +storage + (Some 0x995fdb626195b85107a30d8d6106e7d8c46af3c8f3f6be0bebe198652d2e6c00) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_zero[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_zero[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..0a54f420c2d1e3c95e581512772c573dff5bc69f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_zero[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_random_zero[G1] + +storage + (Some 0x0e134832be250ddb5839670997abb5d7a89811c1335e7db37a321efe001c35422abe6a14ac850eea1acee01cad17c0330c5437362450b8d760a2d1f0e07fb3dc465a4ef1ceb1b026e6314e5a53a7aa4e7c8e5fc77472c691498680d465c593c9) +emitted operations + +big_map diff + + +storage + (Some 0x05ee99471b023ea35057440bf490170def6356133c85549b45895c0a14f45e450fe1fb44305d57a417461cef5a7132ea137b46dde47bee6177d3300341999d6d3dc996d19767d8c30b8b8425b34230813eda03d6db53f8f2b5e2ac99d0d9aa4a) +emitted operations + +big_map diff + + +storage + (Some 0x0e8cc3b0289c1ec90eb49b97da831d4d9bddf1d3ed02e26ca7328ad618945ca288e736aa7c7c06e59ddd34522765eb5f02ca674a5dffe0aab83d25086876d5a87ebcf4d5903125a8f5c637f9ae0618a1f682d5d18c0bfaeeec866c2dbabbe41b) +emitted operations + +big_map diff + + +storage + (Some 0x16fddca3f0f59d49ba43f6861d71d8f4353f6d43899b14311f4914987ad0fb359cd4048b9dc8db6378e302107296037311ec2289dac6db85e45d3dc93673eb3104711664872dc931d4cfe6fcc6a4afded609a738759078d371b5538436180f24) +emitted operations + +big_map diff + + +storage + (Some 0x114f5bff07e03161a9c9fdd20fbb672a71a9aebe2c187e821d4005129278d5d5c195926c7718afda76194b35943339a00efc8c4c040e9b1dbad9ed20768c9c62e4dcdb680bc0add60b218bb42328a116d3e43d579024dfdb4df0f1f0c016d8ec) +emitted operations + +big_map diff + + +storage + (Some 0x0cdd83bdfa776066c37697324ce0a444d064ebb079d99fdb2c03e63563030f824fa95bc7e1c10ad14cd6362857e9a0010073d89e5fae09c29ee2d1a6e8770f7c5a19be2e2e465a50539833b1a463e24d3ea02c606c5990cb8c892200b6e3ec55) +emitted operations + +big_map diff + + +storage + (Some 0x05a3fc74d5c1f3a883631ef0fb7bc08705e85b62786f2d61560ca231e6f7178d10d6c9a97ff5ef4218046e66f9142d1314d8e28bbba2db0f505669a31b4ccb4cb08aab73e175871139b2fff8cf687a0affe2463f0cdcc88f51a4123434533e79) +emitted operations + +big_map diff + + +storage + (Some 0x039b2ab4cabbf7bc5d0851aa4034d4e478e6350a6508d54fe37232e92e5b673ba1bc14db53ebdb317493c9fb3089a25f0ffb75f9a4da47eb6e54be326a07dd56cf8b57a52d49892669f79922569eebedd0848b172deb497b959855b85d66a8c6) +emitted operations + +big_map diff + + +storage + (Some 0x08fe5a710347c0b1a5f1f61c9268778af2611a42f883479e289f1ae28ae1c15408aef3943b951c8377b6a79faefbfbf2150c7fa5f938156c3d8f27b7f5e5143220f5e0752d762ab54a53d9178f4112eddebd4daca6a585cc469be1ab4f5d5ca2) +emitted operations + +big_map diff + + +storage + (Some 0x00d471074aee131574be07c9b749d7bbd09234578fb2acb4a248e6583564b341cb55f2a2b61a227a093a0dbd4bdea67f190a01cd3614435914153e782cf7332911ad79c48a1dbcb8072063f834347441530091809be2c15692b8c0b98ae646bb) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_zero[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_zero[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..26485c3660337e8fe83a1eb41b252cf361ffa93c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_random_zero[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_random_zero[G2] + +storage + (Some 0x131c7f76cfde58ed74ce8c26a4e9c6a6e135fcee1a61a41e5c0f2f33a718d6bfcfb7de2f43d98608b68dcca040c217a6007c5a33c5bb8d523634469302348d23df90d150b28e4f41f1539afa50adf951126233146e4dc98d21a0de35312571b310696279b7105aa5830ef3cfa6df1ff1379f17b24ab561c899e3fc830942e23a4b73019b1ef5110baa4068ba2e8b4c2c09e3b16b0894333f41eccf24b96be85a0d17ef071657b1abfd6fd0e7878aa55d3a5446a9c0ee5b5c293ff8d3cb4722f0) +emitted operations + +big_map diff + + +storage + (Some 0x09de05cde8a5a7a1328aac8335bce420aa41f1077e3be4aa51f93b3a8e822423ef67d263d8042a65bcd89e0091a6b3dc03727a50fd6fc80ed0b1078e81560e759b8013d48261a2cd0e65bc83b9a37cd8e952bcb6a63e5c9ac016d7d588915e0d0fa9247132b7488528ee8f136bc9026f8531c5baacd1647a768bc801e726200b34fcdea976e82d1633e1da82a36cec580f8f3e197860bb36ff010e747a361c54f11003d33b6d3c8c29eaa13be92034b2d9e04a1b6e81fea1911fa8c8b1010b8e) +emitted operations + +big_map diff + + +storage + (Some 0x11d76ee03154c0ee80237e9d757e5fc6fb6f0dff68032489db4edfa4a79d4a2ad8af5854d1b80e5eab6046d236bbc97b16a1dbe3dfeac51233c05fb1ce011cffa48dd38b052ff81783cca048ce5d7c44743a57feceee2512aeeb75344fc0123a18459f774f0e6474bf80a154a754e3abfd281dad0a967cdbfe25e98e8d0a22a41c41f0822fffcd3d92a519b40d48f9b109f79370c21568150d9dfbbdbb3187605e4e675280fdc6de9689de0c82083da87a4a776efad2beeb2b2a8e238faf0543) +emitted operations + +big_map diff + + +storage + (Some 0x056ddeca0596e44d080a38cb233517d706f5529482d8e7cf5618e2c1b17222bb3cf9627173a05ed34c19e925244c775d0bae3e10aead5ef97474d420845b1752c054222387e5767797f2ecbebee3f002e930c7ecc666719760a2a7625590d2261360cf5c50023104c36e79765707275f0517283f1834b3b378946f48675459342b701b5d421af115764b639736ec666712e9e21a5028fa9958afb36e610e74bbfe0db03a3147409e11b2d12e45513f0ed91cae918ab723773aa1d16956754b7a) +emitted operations + +big_map diff + + +storage + (Some 0x016319cfc0cc2f9682f2171aee2448828d2dae206cd4eee18485d4d528dbe42d91331c54b99071c54f60852279bee33408843ad79e654427d875c5ac932a82596e88bfd0ed1e7bedeac67cd6d260730a1bfdeb7ee072c10bac1536b77b89ecb614f3b216d3ef4cbf7d12fb26d61e5e3b50ef7fde0ec13311606c55ec631935f5abe99ffced1ff1879df289694091866f088752642b4791b742acef63b6c7068f2789c7a5c37c5b923c9f855deeb15af919537ebc700f0754a5b3cf76a4aeb585) +emitted operations + +big_map diff + + +storage + (Some 0x0487d5eefd82485134b6dc3eb070ad29f24b283e66b21b7ab89dc9837833d577282d6886900daca411e1251851c6898a14540427013fd1777ff4bc6caa17c499b45714fd944c23123c21996f08ddf9c841be93bbc3b427f3e97bcc96f0d2dc80076e1cf2b08d1e061e5dc05d04a9700f0f498c55740cdb07513113481cb2be4ec8b2445c06207bd49199f8784321e3e6188f33ed153ccd194cce9574678af873a515e2fc683d1e949131ec946e212e80c4b48876ac5b4329ebd66e30c3e64716) +emitted operations + +big_map diff + + +storage + (Some 0x1825a997ebad0d60dff12bad0b182818c5939c85bb90df49815f161f160c34b007b765d5f45bf8be5714f5687e8ed52d0067d80904c49cf9f9d7a6f6b6748ef1722a4fe7e5c3ad6e4535188dab7b4fd756e024bff36798349a6b3796d4e0eba00e4a44260a6527af74bc062df2fd3d922b04052e654483234d944edfa3e81b9432d16b804deca1690a2a6ffd276fda7e0f427e3315cf2555c0d3d146715393a24939b0bf36d6284c672a212f7e7902ee2e873281d396290bf26af6b3a330f058) +emitted operations + +big_map diff + + +storage + (Some 0x14fd9f5cb51b90075b3250c91c45be2eeabc425584b7b451539f238c191ad58c6c364020ec6a8ae1810fcd6a894999da065bb45ad11327c28d9bcb1fe85d45b10a2e42fbb1f3eef622a8c261e52ae5207840c8805fd2b8448c7f97aaff8bcb710cba0f99825e190b5de72f359c21058d3a17a30799f1d1552dd1128aeed5ef96ba586e62fd71a004cda332362df3d70b15816951c6070599f40ac6a1bff7d8c21744f00da365ac6c2b81e7abc752a01736e089226911da70e7b908a130af37b3) +emitted operations + +big_map diff + + +storage + (Some 0x07c239bc8ae325e0ea294eb2d7a8134c9986099cdae78224b2326f9d419769b065570154776fa16b98c1b5bf2f69eef41403ed7557754558c686ad6c00cc61b386f3a2a8185d1738e9c6ff6cdf9353ae1a30265ed02828a2979de0e8f10b15d3087901b1d719a2fdf367564719fb05a9196c282f244ef434090e39ff091feb12c45c117c2d68e36e8bf37aa7b7847213110f3424cea97cca09e3939d418883ef7f394715e5448f833fa0ff61ebc8c9d9fc5ecbe8d2480f4955cda3097cd72289) +emitted operations + +big_map diff + + +storage + (Some 0x070a718668a1f4e692191f9a7653827f6051848cfa72df0c3e99fcffcdd9e09267f8e6711948b43565699d4bf02feb0f0faacfa8e44cb5c50d2d07a54c811a0fb86a1e0f565efe32ec11bc147ec6f8073067c6330afe0c5be6ec5962921f58bf0b97bb667d15b6b0596cfe29f41fd994c1ff7332dea6699dd72f828593485a97d72f8322ba503653a6a82a42dfe68eb9166bfb6fe8478bea584d01d252c7e256bbae17b371a8bb87916ddfdbcb28ebb7f4670ce1dd3be5067e38b0e9c9f17140) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_one[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_one[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..e86876ba182fa5376a696c4b9a3d86f8479f5f94 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_one[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_zero_one[Fr] + +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_one[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_one[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..a0d286f5da6d7b940fb729fa1b0e8b3d623091f8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_one[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_zero_one[G1] + +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_one[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_one[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..7b5887b13ddb2b144dd8e0560ee108ff718da873 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_one[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_zero_one[G2] + +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_random[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_random[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..4b7e1d5400206c3ebe0ac76acd6586b521dcd10c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_random[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_zero_random[Fr] + +storage + (Some 0x6b1f61b3ffa8e49f9a840c0f4114fbc6061bf98a51e51fe4a396f041c50f5e02) +emitted operations + +big_map diff + + +storage + (Some 0x0e4c13a518d43c1a04ca2b7b16ca21d8f2443a861e7b6184a85cee5892916903) +emitted operations + +big_map diff + + +storage + (Some 0xa18e92f24830c77e59167062c6e8b22c08b86800c498b932bffaccb68fa1b934) +emitted operations + +big_map diff + + +storage + (Some 0xa91c486e8bdcba53453336ed752ef9b214926a2b3ab452552a31eda0ef3cfd3b) +emitted operations + +big_map diff + + +storage + (Some 0x0b9fb344957ac93904848f30fb9c068ca7c9cbdd6006445489226be02676026c) +emitted operations + +big_map diff + + +storage + (Some 0xdad4e76170b71edf3c7ae65a00659f332dfa08e9d2cec5a632f8100cf938ac62) +emitted operations + +big_map diff + + +storage + (Some 0xdcb9d72844fc8c9d4e25acafc2c1945f1f8b0556817c333f0e6c0e5c932f4c5f) +emitted operations + +big_map diff + + +storage + (Some 0x53745aa1b2b2734a0b038307fec0d0f20e6ce9d512a4ccca1ce49dc8b294b93e) +emitted operations + +big_map diff + + +storage + (Some 0xb1cc9dcc3ba2a71687b388d23758da47c067e1fa6f0b185fd5d39b9050416a12) +emitted operations + +big_map diff + + +storage + (Some 0xdad6443c3e503dc862ecd96031f0f5c40fc4560b73313dc153bac7118338aa14) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_random[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_random[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..5bc52492c6a31eb0f4435e5e369e90546a68c041 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_random[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_zero_random[G1] + +storage + (Some 0x043d39d06dae5a1faa8e462a13a7254b8ca438e47c7846fbeeef71e44379e7df2e29613e18d658ab0da4547b4f3852590831612b23e928a01f20857216d823ca7c5e07fbda46923ea626380c4c95cc2046b9b228ffc599eee8ae2788484a1e4c) +emitted operations + +big_map diff + + +storage + (Some 0x05b38be001d64a2d9e17a27d90e29b9f8f8bb28c7c8720371e7f72612f0306a97162cad563ee5af54df372c89035a2830404865f74dde79ccf6640806f47cfa66373656335a4ad64cb383ee44f339707678730d141cefb643ae5a7ca36fd2b0f) +emitted operations + +big_map diff + + +storage + (Some 0x0f644fff548f117895a24c9e4345c4dfb995caaeb5a01c1bd8092677f0dda287a03d7c86b0cb50a61739e21a5950de540abf3818624bd6f162d808aa8ff6b9993ce584fecf10d3aad86ef521545f2b5dc76839620e52d27f42fbc7d9e548b250) +emitted operations + +big_map diff + + +storage + (Some 0x0dd72a72f8dc7d26d4f54ce50d6bac81bad784cf2b886d5d2ff66a06f5358e945c5c70b81693ace7d21e6fdf8db436820d5f1d73d015e5799f7fe9a1e4068fee0e6874f3e8c56f85f673e0b1cba80511b1f4bbc02d8461b2919bf8cdbdf9a051) +emitted operations + +big_map diff + + +storage + (Some 0x0da1488962b00f17e629884dee4f153e0a717af426bde7c75da0f5067ea5e63297ba068bc230e5179081af8a23c5d5b618f5b3bdae5915cd2724687e228a4c1843578a0c2aa2297031745fc1f3b77024851cad2bdb815197fbc1d76e7dc17e7d) +emitted operations + +big_map diff + + +storage + (Some 0x153d1e9eaba3bb00055584ad97fe9b49fa83bad011d1b97598bfac9db9c54a8ee0152887ddb42d1d46ac4d4ff97da3210e5d38c8b1f74d70b56e94f953a289ca8604fe6731498987c3bd186fb24f569a0c403c0173dfa6765f1cbcc75248547b) +emitted operations + +big_map diff + + +storage + (Some 0x0165ba92201bc7848e74e23c842141407b407f09ae7922e01a290c4268579c84f2a3bdc20a8a1005e9669064ad2e634405e460b2eb3026d92cd2833ae7d1f5a009756ac91c58f2ca88a358c9312de31f9caec97acad38cdbf9f1f8c844ec23ee) +emitted operations + +big_map diff + + +storage + (Some 0x02bbf3966383231f6c0b5a0fd62240867a8944331afa0c6d06b5f1bf83d3c2eb5a37edde3f51860afe887526e343fafe007cd4b0abe3d4868391ccc730e997525108e17740b0edbed0d1cc15bbe411f33e35232ae16e79c77b6acf22ae67210e) +emitted operations + +big_map diff + + +storage + (Some 0x0ec1ff5c67f23f47f82e834bce1d48e56e76b78f42d7ee530e660718c3cac29f207d58aa4c231376f8a8ea4951f37d680991eb20bfd4c9033acda6621b2861bcd983a1066f6add9510215cfe0e66485e6433331232d37d944d1cb56230727b1b) +emitted operations + +big_map diff + + +storage + (Some 0x0b020051cc583ef24590ef0626e7bb42d30556013f5b490c78bd1c689c759e04e3865f04b6807f9b7a52e4f4fd23a4a70684f9d93f58388210075b8de217efbcdbaa41c4c7126dc925c1263d36953db065b15d7fbdd248857651db0f6229ee89) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_random[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_random[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..9aa2ca8fe400aef493480a788c0305ffc8160157 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_random[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_zero_random[G2] + +storage + (Some 0x0a8801dd5d45269185fef3af4c71e27aa302f843c4f75ce58267d5cba2588d63e240629f85cb551fca316f32709a3c6e02487c3309ffda4098b64d73d16074121a6a8bd6ffe89151c45ddd7381e05b7243db96e4f6edfa06c57d0bb0265b20bf03d1c067162e0dda121fa11b9c7dfbd14a027f8b5af1630ab703a146b9a5ec97e820133a732fdf0f438814a693e77a820edf72b5820459bcb682af727b7590463ff39b863dffd2a9839fca3f6530b13942c53a5ba928be5b039b125b88716729) +emitted operations + +big_map diff + + +storage + (Some 0x0afc630b73b1d1b407c89c797f07acf80710dfa9ce57b46722e7dcb8a43a847341372d2eedfd6c2a3c42305306ed468512fd95cfceec1194d749b13948f699beea5b33aeacb902d2e12a2b65e9589c57d26251b350edd142cec634b23a7318bf1553647560e99b285b82153ba4f70fb7c3f494fe5cb65c0b7f1446adedc646d14628f45b4b8d7a22510b8551490b04cf0a0103d13a5deb5d68d32a85189cccf1134dd908da9ea8ee034d067f729d892bad11a45113f0e5f5ab25c021759417f2) +emitted operations + +big_map diff + + +storage + (Some 0x0b8026c50e2cf76e4fc00cf25ada386641261fbe457250746098edbe44d28eb0961b4f4aa7d3d3f65e0f3d0d92a131ef17cf0aa479c55d0c529b2ca05b8488adf9dd829d91f0bec387c5e91ff7082678c6e76a74649279bb327f3a4f3cc73d80104e0f1880c6647428a0b7a5883214cb46255a49c13cf4d8106818b782078ef1007f7e34790535e97ebf8b1cbf3b723317b7223c824964da23c4b6bd421a76603c0dfc8f2779acdea5cdb721f71dd9fd44f9488ad519057def31360c1673e5e3) +emitted operations + +big_map diff + + +storage + (Some 0x0fd3a77a6a919626d31505fbf7ea71d3f60b78dffb1b7232c1b3569dbb67381aa9df4ab99aa25934912112b2b9f1612004b3c9f71504341d8abb591f6d7ba5b9309217467d332b6ae66d634937a112cba73009befc554a2f9c6701d65a29e8cb1525e405ef803bf935000e2b0ed5b7ba1106dce0369069391fda557b7282e7ca77513fea88f364dbfb17ca9b9c308a860760a41f8268069fe3f9f84002add2e2e14b6a4497b3ef826fc885a633050c1d9852e942006aeb234d2944e17a5afc58) +emitted operations + +big_map diff + + +storage + (Some 0x00ea54ce4ab2f8cea7e6f172c249638844225c5e72980030f45e5645680d9f2860ff22d0310d7e2a39b70b2fd2e91fbb099428b8e20bc8895f9e9308b66c8afaaa06f1bea33ff8dd55524d1206e22278e1e4b23aa1eda324bd1446467a995f400fc4d7ab9df219f5af91a3bab904077f36e25450bbbe708f5f4d5a1f0fc3383af24a86ccd3f424bb1acaa65015c0fd9e0e5020e8ac03981166b9ced9b74e0712424e60950c9a774daa4d2677290794c5a34dad95b9e6123d83adb9dfb84acd22) +emitted operations + +big_map diff + + +storage + (Some 0x1667ce729e66b328dfddd67b3308183f2adba83792b637a9d6a54ee5c520f4a84b6d4446e906650ef19be90956246a12109589b3b1c2694b39d3d5ab8a3d2570e70b15a3ce81fdf28b488f90fe54809069b3143faeadf4392fa41b0178382e8e05579ff476cc9290b1847ed3895beebdc1c2fa106cc097ad369d2652b57feffee233a9f8e879164a649e59b7cb22fbef1252d6ab8cf8376f56df57627a064a206843d58ea6fefb53a07088c93786d13f47a91a07839b58d0d230598709bf12eb) +emitted operations + +big_map diff + + +storage + (Some 0x042c1082a0a914a892b975934ca4b161aa2b2c3d45600fc565d71047c95b1e6f0348534309ca6f506f74f1089187507f099ce83b41b120cd8b8d7a6bfec0cfbbeb90a5936ca9dd386e2335eb8c12f9a84ad4ad2a1ecf69bf05427bbe96482384112b2326686e63c03d9f3ded29536fe476366b1ec177c016370ad1b21c93970dfe04779be2dbdcbd1a306f5c6ca9f5bb0629414f83ae3549ab79ee283fb0be885a9706355efc1aa0d0ae6243118e7ac6cc8303e68d0afeaaf6add5d41caa7b57) +emitted operations + +big_map diff + + +storage + (Some 0x191f9cec71fc06393c562a77e79041f3851837dc39efa4b458bb55b6f89e15c8fef9dbadb3f75b4b9873c094503742210deb4371bb8293c102c122bef0c8972b6dcb4f9add18109234c3b94400e3e5ceb52f59beb33ca036c89bb60ad7b629e80ffff89bfcbc65f23e1ce932cf2992530fcb0056901ea31cc425585fcd63b444e2ee671eb7109b0978d23a19ab468387087dda6c1354fc4b645d3f0a6975eef41ba75a14b4450db71f4d899e71d4fa7a52b275b06e1ffdf36f539244c69654de) +emitted operations + +big_map diff + + +storage + (Some 0x091703cb9cd4ba012c631f8be02f949e9c488987c6144dd8a1660a4eb65a41474cac5edeb65824214875ee21298fee01083224b8cb2bcb353c47a796567b823aa8075d28e9e8ed55895dbdbfa8efe589c8c58218308bdf4d7737b27b0c6daeae17b36d402a7f7ea148c3fba6ec80633d64cfce6b31d055bff659b875ce0b513f4bbfd5e79580f1a5d896e551f082ef3912efabf6b0dadbc53fa3e03aab4817ad547fc2877f4850ed5861e37ccc29115c203f6c92154a84f898ac1fce677f702d) +emitted operations + +big_map diff + + +storage + (Some 0x0ed6b993962b955b8fbd1b7e7207ee2faad1460282274305837f89ed9081a405ad1a088f9d46487015b082db7ce3c80f09408e6d2f2e02868d1be1dcf067c8143a887921dc7098ef4c116800562a2786611a65b437ade3db1629d5eaf3b8eb56199fd734d8017287f5b24d4b4f0afae0cc86db7e751d2e1cb25d06f6bb3c7ba69c3b5d94a6913e9e1c8d870fb1a4470a1864d95b7519f8d7230465df4fc23e7f08fb912a467496a58b024b0e82ea5b8cac35aeceb1509db29b2f5bcde0c2d5b8) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_zero[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_zero[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..52a8c96e7f76faf34e26c9c9a68069be61eb4081 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_zero[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_zero_zero[Fr] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_zero[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_zero[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..ba674e67477751ce3ec726668453dcacb6c9651a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_zero[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_zero_zero[G1] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_zero[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_zero[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..edc86ad7a90c18df45807a06306e9850fee47e52 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_add_zero_zero[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_add_zero_zero[G2] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_fr_bytes_parameters_more_than_32_bytes.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_fr_bytes_parameters_more_than_32_bytes.out new file mode 100644 index 0000000000000000000000000000000000000000..bb5e0df6f2870604625ea7a7c3bc304d59ee56cc --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_fr_bytes_parameters_more_than_32_bytes.out @@ -0,0 +1,8 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_fr_bytes_parameters_more_than_32_bytes + +Invalid argument passed to contract KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi. +At (unshown) location 0, value + 0xf7ef66f95c90b2f953eb0555af65f22095d4f54b40ea8c6dcc2014740e8662c16bb8786723 +is invalid for type bls12_381_fr. +Fatal error: + error running script diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_groth16.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_groth16.out new file mode 100644 index 0000000000000000000000000000000000000000..c38390152bf1d9a69c3190159b43075dd242c576 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_groth16.out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_groth16 + +storage + Unit +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_one[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_one[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..c82a90d7d15c4dcffb59aca04b4dc542c18c7f0a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_one[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_one_one[Fr] + +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_one[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_one[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..a9d9f408fdd64de5de960a535f3ea83ed56559c2 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_one[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_one_one[G1] + +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_one[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_one[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..6bf64b6b13fe96eb346538d0df797100f9a60d42 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_one[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_one_one[G2] + +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_random[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_random[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..a4c18da576a3fabbb1d25c63ceedafe13fb1327d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_random[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_one_random[Fr] + +storage + (Some 0x3a14168aa51fae4ac33e62e94267e61ced8f00785e295c9c7125b881afbe111a) +emitted operations + +big_map diff + + +storage + (Some 0xe842c1ffe3c767806c91f42120e27cda0e3578a1c52c53e1b33a65cff1e22b1b) +emitted operations + +big_map diff + + +storage + (Some 0xeafb8e3cf1e223497893cdc3130c6c13aa7d3d3e6a3502034d19d3ef4a39ee18) +emitted operations + +big_map diff + + +storage + (Some 0x614e3f935e4b1511d8b63143d2a7e3bb2235c5f1b1a8597f44347c4ff1e7764d) +emitted operations + +big_map diff + + +storage + (Some 0xb34999b9256eb7205c0303553559e8b14668241277fc207b21ec9aadc4451a1d) +emitted operations + +big_map diff + + +storage + (Some 0x307b86cff0794406b7e07ff937fa843c09a4e0dade758b297e39569dd41c5b04) +emitted operations + +big_map diff + + +storage + (Some 0x6322ae545e19b2b35e4649e021b2025caa9df47de27b69e023c71e349fb8643c) +emitted operations + +big_map diff + + +storage + (Some 0x36d7ee80fb7f1e6bc31f1384ed67d8c5b195f4daf6ca413e64703cbc4e9d0d53) +emitted operations + +big_map diff + + +storage + (Some 0xfc6cd59996ca5aa047bd59b6001a43e3777d9b19ae65de6ce8c2ef7f52cf1c4a) +emitted operations + +big_map diff + + +storage + (Some 0x6e9f624533c9bed9c971db028e9bd5ad034d25d38f1387b090a2cea2685fcf16) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_random[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_random[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..0807216c6343e551083ef18314daf336918d2a8a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_random[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_one_random[G1] + +storage + (Some 0x0e3c67b12372907bb20da67474058dd766c165200d525b1e0ccb5ff5e3f2c8ab66ce557601ee6f39a81d7f89715e350303ca13302a0866206377c197d62d8e5149dfe3b944179af3646b886a0bb16b89e9864a7bbf89f18d1177c1c010213e4b) +emitted operations + +big_map diff + + +storage + (Some 0x1627a49ada91f905e37da3cb998e77177177866dfa21b714e8e60a969d993dea22dfea1468ec27bb502abffecd297af208a8954ec9b70cce4b5f045e9ad030e1e3a9e822ba31fc9ecda63f7483ed87dd251c117657f331ed316161c22ebd9a8b) +emitted operations + +big_map diff + + +storage + (Some 0x0044c4f40be86203e6d9879fe49fb510b1e40b1a58e26db3265f5c62b49ee1311f12f1e8fd034be3f4027c1a5dcdf0610a721358155dde11af7e315a1246f483973321095593a72d236149904a4761ec3134b482ef46851052e78e24fad5fa2d) +emitted operations + +big_map diff + + +storage + (Some 0x140bc58ab952ed42a4fd28fef1f76f5207f8202f15bb12375d8a4102a6c9323cdf80dca17ee79d1a80cb438b56f75a901822447a54c0b4858e2dbede0ed4634ee0d0f190c2b0f347247da09edc81cbbfcf2f5be25b842cf1777e151582ab797b) +emitted operations + +big_map diff + + +storage + (Some 0x0413f511b1c65f6a27766c69d4518eff63f9bb913feede2c82b7943f620feb27772f48b1a8b0196b88935a8b67eef112038f995b978f71a5d2d0470d026ae5c786be0ebe748045399a688f550e4950f2b5e0bea6131466d72a8eb4c6fbf2f750) +emitted operations + +big_map diff + + +storage + (Some 0x00e088d901aec4f3701eba2206c722276395202270c2a66471a5442861ef6ba997f2b12686e7b5413b24db4aec0babb207e5f81cccca63d939853e1b389695d58e907550fe6e4b347d870ab526b2b7667b888b92182366b5300314dc2fe305d0) +emitted operations + +big_map diff + + +storage + (Some 0x11641aa9417f8eb1659c74cd4a8f180242283634c5b059c497fedd502fad9c6fa00ecc991e978260a7452e79735d5e101559382cd1f3f92d964dc8a3f54b8d7dc37855650bbe11fa9b5e90881002b290951781aee93495d0e5703b35db31bf38) +emitted operations + +big_map diff + + +storage + (Some 0x0804d36e490be2f867fcc99338af37df61df443c73e47bd18f4f6eb8748a31ce403bb3a8aba27f281898a5f8e72f6c4f1321db8c96fffa9893be378e259ea6534fa1aa8be504b3f896e2af2a4cc53c6d017dcb587700689d81382f1cb1013f55) +emitted operations + +big_map diff + + +storage + (Some 0x1843835c32147cd7191e2f2aeecfef744f96757e1e5d2427c7cbe351d2142bb5723dc61b6211adfd79d335d632d72cb10d2e0686443369c8f26dd290b98af5e8d892a4085cfd7eac21742b783c57fbc5ee5a5a89a5b2a03ed732a0271bd2b548) +emitted operations + +big_map diff + + +storage + (Some 0x0d8dc00f3ecfb62c9e9e4af0dc3392fc24f2861de4e609b77d8866f561d90904e9e5531b5203cf646d5a22c4a26885520de353e43fb6cf32bbe12b2f243c858ecf9c388cb02be5b935ff8411f76991c00411a40a990d63af69902d0f3dbb18ee) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_random[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_random[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..9d772f0c66b9479b28eca8b0fb04db5ae069ff5c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_random[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_one_random[G2] + +storage + (Some 0x0d95415b2c0375d132c0700938c4590a75498165c923d00317fc3baf5048081b92995c9f651438490ea51f47ae1f871d06450ed22ec65658e7583c95236d3224479355196db6f0e0f8edc6c26c6d1e7c6edd8fc0217d86942a0078705c2188d90b4ccbc374d0076cbd6d0f9f01f4992fc87e8b2b4e17d3d4c91c14e3a0eb33000b34a923350c7a7c6f72f04d64db00320cd31bba7dea1243ddfca66e8e14fbd2b233c2201b43bd099e0f68cb9ce347cabe68ab4f42e972bbcb834d9d73da0eec) +emitted operations + +big_map diff + + +storage + (Some 0x1953081fd90afdd618ed308d2e556cc466cd7c0bdc79bcfcf25b96ece923fe8517e72c98034097d9eee722f737e39a41113223084fa6fd9daab9efb9e0481087c30f3cfef3e046fc2f1bab2a8b142a94335ac957f8521646fe4925cd443430f00c90e874ef50eca42050742f7f605d0f8cfe00c5571a2a99240b88541e3a7c08c91af2bc89ad29b4d397d10d42c93e9b0ac8dff1d86ad777e8b5c6f8880411a139155e8ffa1708e085972bbe6d4d5c4f39415e5ee902c3427d54ea84334b7ff3) +emitted operations + +big_map diff + + +storage + (Some 0x06a72dbd7d92de83d95290f1d7e8923e0d8e29eb84024b18fcea2097225481c29fbbbe7d030ff1b4018f12418b9c28a60728f0e17309868072e1dc188bc9548e4f3a0d4fc35ea2203f42539b462b7070feea8293fe47818fe89809ad977179620d727fc335198a6ddbb9e4ba25def0445c22c227bbd811cb005828b2d42024d1ccba6c20d5987bfe9ce114ca112c04b50d142f815aa648bdfb092e5509b72013b6417e6f5b5ada3cc590a6d4ba0ba908afc6ab5dc5a34ae976afc74d8e75da1d) +emitted operations + +big_map diff + + +storage + (Some 0x13ff1086d5713b7931883f01c36424ef26d28dd314473c073ca3ade1da5e8fcd7e22a86f0514beeb5b16f53176bb8ac70d8fe482a5ff16db0f19ac5738b52efc3f9228a997da35fa8e3a2cc9aea049fb23fbf5926f199ed7f29c73022610e4e70ca6547613b84940c90bfe7438339770ee180237cf717b67d2eac23fee8c42c17e0a5a903e0eeaf854856a241781298e0b13af3d210efad5757c6112565bffdcdbf649ba5b645d6d1a46fdea5014d2f3edf257af5ec593fbf69f14f0d8e3ef24) +emitted operations + +big_map diff + + +storage + (Some 0x0f3012df11a5a21ea69e484e3b1aae6426f47131b6c8de2d2ddcf5f08b7e2264beab80d08bdc3464e5ba93ae5c70dfa81792d5af6898237318173dee0241ad29f3a243837764dc8a5f66deb5868fd69ab434912233d3ccdedde5b8ee484a4b6f07ce143b9d525568a35c28ce4ad2ab57463cdc2fd6cd967864e130645e0f2807bf13228b000a2dc124dd4fa45bcee53202b486642d735da0ad84458ff8989cdfe9ff1478b2d80b4e45dad71d7098bffc890d65b720372793fc0ce9c6fc169b0c) +emitted operations + +big_map diff + + +storage + (Some 0x1429e92a93f2ba48ebe5d66ecfaa3b148e8414beae4aa83b5c054caf6937f30821e23621e278e197966ab69806010819156379b3a6f4674207d680dbd0e45a1399efe202631f30507fa96d88c4363bbe852e95edabd9902bc72485e6dce044a0072da73fb04a55e27613ddadd5915d0637f5756e4a489eb29347e76fb329c0e289a156f8e758ccbec03376ccd67a528a0abaa11be4c810443b52082cb54174e2019ea8d9d7373c99e103908da27c1aab943e745d5026304527528def70f391ad) +emitted operations + +big_map diff + + +storage + (Some 0x07d9eda0c029333aa344535a1520d5e1ff32767edc4a9d2f963fae4bf7a76762a1402a70fe2497059912016e20a082a20faff41e659f197f5c99532070782107a586dbd7e6609b31b89b4e91d5eb85ea01aac0e19aaeba32f86090c9f489b1ab0f8c51be59ebfd70a90246e364f817054a149dbc7fb6ad6e5ed3991c3e55f6dd08bcffc0f9e1e7d1c4fef6ed7141aced0da4ff47847aa5f5d7347bdf698525b75c840569e1dc731c1971eafebb305e77d44b2b06737a9f60d3b0cefe5a3412eb) +emitted operations + +big_map diff + + +storage + (Some 0x1047eb6211bae046da85a8085a23c5df6f73ed25abb394b16fa673842d19107b2e40ab9289b36f2699dfe34f5fecd2ad0596e9d73d3b697bb342d5b4a74922fac2c0ba20ed89db874e23dc07ef1c02df48ed3b5f2b9e63e1749b65d64ff3572c1034d01a148145d63b85d0f01b7c84c47ead9963b84233ce9f5cc48b1cee86b094087fba5d718ab4aa8a09153b078aa6036351a3042bfeff633a6e023945a0b6d88bd82cebf4c4b9010d16f98a30299ba276f8451ce728c26010a05bd09ba365) +emitted operations + +big_map diff + + +storage + (Some 0x0acd7057df12eccc09376a20c70c6c054bdd064503446d525413fc494251c0f19181eeb1280c83b6d34916a3904900bf177981828b72d00113c22542eda6e9130fe13f4b9d2f3dc2a78962fac295596cfa28f95bff49e35358f8a85cc764f2030dbadceba39d7e87f274f1b22e0d1f92e79a4452c6a97efad1aa6a71ba2987d6506341c1b8f9352548cdd40f445e545b051e6665e110109b6e80894d973b10ab4469a21d5d167563c2ac7645523fae0a2ae2745318b660f2cd19d725c3a17fda) +emitted operations + +big_map diff + + +storage + (Some 0x04f081fba03150088bdfae16217e3785de649dd8866c728a2ce05abb271cdb664a45d8c539f1a6c7b42335e5beb4a97e07c41c2e946a74f95d390b574fde8df58bda9d43fa695b02ea8cd290949097ba7cec710d802cfbce1a804c74e8b6826a017b201bf0b344cf7d469ebb203b4eb2b7ca41b6f7cd3797423276d55742542d9435b6261956076718a1eaf5fcdf0f1a127b43756c11c7baf603bfb4f929933ad5c263c9774bd6eee6131705416739a15d49c87bbe0a182ab62f70f55db77144) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_zero[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_zero[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..88822ffafcb498fd459474a02c921364b3b67a03 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_zero[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_one_zero[Fr] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_zero[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_zero[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..c468caeab496617a74ca1b798ccfed33b2b1e9ab --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_zero[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_one_zero[G1] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_zero[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_zero[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..e42bb9fcfc6f61fd2a7968b75783ce6e9549a5b8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_one_zero[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_one_zero[G2] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_one[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_one[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..d696337e05cb4aaa4cf6d12e877b8ca283435c82 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_one[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_random_one[Fr] + +storage + (Some 0x286f0ec6252484c8bb981a3b8382b975c4ea92e11d1889a4bac541d0657db547) +emitted operations + +big_map diff + + +storage + (Some 0xd3b3ab5cfdfbd937887b10406248e8afef754b2692568adeca80be1c7abe3057) +emitted operations + +big_map diff + + +storage + (Some 0x469fba7341e28e67f35affe2fe4b97662a8b6481cf297346ee94e3d7d932c92d) +emitted operations + +big_map diff + + +storage + (Some 0x8a7177b61d33e4cb78eead124de5a06175df7e3b59f3bc4dca273de59b8a4151) +emitted operations + +big_map diff + + +storage + (Some 0x252050ca68bc0bc7940a33b68e12982233df654e652e96f2d28ab32be9ba046c) +emitted operations + +big_map diff + + +storage + (Some 0xae809d9a60de4be2126f115a819b9399358c9063790951f0373420a664335748) +emitted operations + +big_map diff + + +storage + (Some 0x128327880e041a2d6890d969f494c5581025dc3cdc3e3b6ce2d790f8ee68821e) +emitted operations + +big_map diff + + +storage + (Some 0x709b3e567cd3889a553a34818720157dd38724cf85ff458cfa91cb624db84b72) +emitted operations + +big_map diff + + +storage + (Some 0x932b426e549c4acc360611dfca579d436d7ce59111cb3f2bce5e9fa1562d4c1c) +emitted operations + +big_map diff + + +storage + (Some 0xef9144b2686c7a1de7488aeb9669bc3dafce03e580b27796d5489bbc2d5cef30) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_one[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_one[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..f8b6ecf6524e8ad3f4e7e1d71ec06b132d06d405 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_one[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_random_one[G1] + +storage + (Some 0x121ad63b7b9c90355f2862d56fe793c29fd884e311a65917f860071464068682612e78f29d936ceea7056ccd2506f12d03ffb304ff19fd039c7404c0af9119775534e2d93c5f9fe172893767c1dc12a25edfff52434bd309aed1d54bd0a89fc4) +emitted operations + +big_map diff + + +storage + (Some 0x0538edb42138a4fec97b74645550b722d7e87ccdea13249fe9fbad25e314d8587287821622e9c7cbd8b5ffc5b244a5c70600605fd5a514fbf6d13764bdb35639fc7edb3b95006fad00083bdb65420ac4a2b7a5a67100ec7b0fed8cc3f5bcf251) +emitted operations + +big_map diff + + +storage + (Some 0x0e4b6dbffad2f4b3ff5be58477f3dca892a060954b35a0ba682a9e388071023d32e4d4f241d6b926348d1b76b78369af05485f02b87fe3666c70f04ed7439d175fcd2d76fb9790cd4fea48c38f2fa1194799208195286274a0c94aa4e7225c1b) +emitted operations + +big_map diff + + +storage + (Some 0x0ef689c3ad66bbc9bdb16bae245346c3e1d314091c15b37622720ef5e70defd6c59d2f4e4335c791644c28f967aa5a510607bc31d79aa0a40fe637c47fd825bc06c7ae7839eaeca4a0e4dd8f1589ca8db8b4fee09b91f5a43e04f17ef9ba3c04) +emitted operations + +big_map diff + + +storage + (Some 0x143c03201ff3222e412deca15c6345f6f3a82ea30a8d0b289952dfd4e6edca156617cffdfac43466e7745e5ad5222c7f09b8ed107474064dc0c94140949264aa6b3aec28772a8b1b3dd0571ecf433ccc9a7e51d2ac119b7bbeadec90d1f3c837) +emitted operations + +big_map diff + + +storage + (Some 0x122c5f9870721941131cbed468f1c754dc52f494fcd486dc761b4281e17eb41d29a40a983de68cec836a36f6d3c396e1054b6904fd965d74805b1c088ac71e7b5eeb41a1611b399c63777170365859ce68ed99bfde5158a207ade9807f5cc458) +emitted operations + +big_map diff + + +storage + (Some 0x0fbe56abacb7f089a1e46ca6d2837b8f98e51dd1054445c2dc599deec36800688b6add762d6eaea36823fe5e867955730f1c175b454fb0bae81377a0b30a0017d2c11b4a768b78679e8634e8d2567874ef10b5f523f2e7bf8e4698311de58051) +emitted operations + +big_map diff + + +storage + (Some 0x05014fcf35b18ed937a24b4ec2f635e371e331766f6971204a6d458c6876381476ed691a0d020a6b487b14cf4512fcc20678c937e35d63f63e52af3fd081162d4c34a1333ebcc40841a7bccec941e8596956cb56bae1d2768ce7dcebb31ed170) +emitted operations + +big_map diff + + +storage + (Some 0x016f4c61393eacd1b8365656d475d00271c146649018368fe2b0acb056daa92e133a45acc5ebc121d100673f49a55b1f0a91f97170f0ac67e8f8fa516a173fae35645c26748696f5d6b2094d0a4e5a8402f59cde699ff5627d3f16034d745174) +emitted operations + +big_map diff + + +storage + (Some 0x0a8fdae48244aa6f45cb349ccf56b7dce450c08036f96ca38a13ac8ba3c136bd9bd83a91559c7f5269f4e7f34f001e6d0152b902148420a763d285716810dd24cc17b9b486e8578ad7dbedeee3a4eab0d1ad73cbd3a1ea783b875b171d897030) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_one[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_one[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..d00b14447f14b87cf927ae51da2047bcc9643a86 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_one[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_random_one[G2] + +storage + (Some 0x09437976147a4d0d174d809df2b91247f2e2a482fa928fed9817b1740ddd941be108809ec427bba3abebab29e0fc91360dd9f11f94ec1c4cc3da10c13df7fe0a3e089b48c7f129c02c3fc47211f895c2243242f1a238cfca841e8d9d1e7927e400b626a5e4a4bf8f147aa6cd82073d5ec66504722a4ac8cf5939d5676a8b2b37731c94dce4e64ba9862eb657d17d789c19b1fb83a099335db3c569279fad3516257eef911af59c39e72a10da16e2c87394bee5a58b107c55ae00470377dea973) +emitted operations + +big_map diff + + +storage + (Some 0x05ef75bfe22c1366532a0be4e76af4f44c83653e53e7441e31eafd50d23f406093a42d56830ea0b2d6bd72c946c82bd6020366ebc02291ce6864c9923414fa0db8065979cd8031a84ab0bfe58ffa7d97c4f5829fc22126f8818d2b30cec132250207685a42ebd4b3566d3ae6437b12d1397ff6101d5cafb3283c0a26113b39436141bf2a09ec817d49145171a7cb0b4005483eff64cc380f7fab70479ff783e05b0c6a15245c93b732d9483adc38a3beb0179f766e685fae2ac8b91b888a4f3f) +emitted operations + +big_map diff + + +storage + (Some 0x16f479fc7f990fe798762da4e839ae6ab1c3ea82caa08d6d5892f28585b14ae178dcec9cbfe6f1a8128dcd46b87df07609798415e658f9387aa6138fbe3c335fb2327ffd2504c3f5aebd3285a2d08fc9966e8dd12f1c70dfdb369cc98f67b712179379ea1fd9bf46362cd7878a3667aa89f8c08627ad8d60868f219d49ed36336e393e0b7ebccd9027edbe634ab2d44507d065115a3ab3f4bd2ec1bb6361f580aa0040ccb0501426bd186e1e1971f7575e1e12ce77c8c2d8269799dd380de810) +emitted operations + +big_map diff + + +storage + (Some 0x04ff37dc37877f596cf0fee3190b74567c6925c5822c8776a1fdb926d250ecbd59c16109b3e18bf6389fd29a51f9815904b4d3277553a1afed4dc7c441cd16078016edf441df1bd21bf3590b701727a7a4ee5cfb77b4af06f154fcfe47cb44f91400cebb1f66c59f2ef796b5d8309c6d20a948156624e4d46ac09bc6b2566c115d2bc989e53137ee0bfa6e2e17d7b6fd10448f47c61b0fead5e32eb9f24f1f7635730a822166aa400d5537614fbf808d6e40f92746d6932993e74c3b57ef1520) +emitted operations + +big_map diff + + +storage + (Some 0x0b7028a94c140119e30ec04b76f245e78dc6d9828bcb5f503f44f2048faa675fac874f88b058c9b6e9ea2fb878a931fe0606479ff1fbaa8f8a1caa797ee960de8ee345eaef846578e7c6eef78aaa1a16c9cb9985821639cea2ec5866219d77de1593c6981c3da9e8c0a64bd8aa12a12d83e03494bf94ce9b098feb97a8921fc3a4a2656ba5a5eb130210b66766a0dc8512eb97e67cd5fe60859f1810ec7a1237fd80d4cb73e8641e1990a0e9e5c61f738ad8125b9108d78f96d704f3d43c71cd) +emitted operations + +big_map diff + + +storage + (Some 0x0f3e9c3968ce220c8d22fa306fd12e8afd05be41538ce630650650c8461563267ee4eb22e87818cd9e9022a1c23641d50b904a7acea602f907c97fb8701fe29fd6b2a276052b1d5cc152510016c466fe3ffb38ebdc0036058383c7643efaf10f07e7a1e694e4618c2057f4070912400e0c1457b32223be85ceb98afc5a9891ef467bbd4f96aeaf59dd92f39fd7698d4a1464d7b940f605a0afb023c06b2316ae5ce3e522e10e9e67ec2bc5dfef45e85e1272e5d4c26a7eb6b5255eea7117bea5) +emitted operations + +big_map diff + + +storage + (Some 0x17b906ef7baf4816f9ff3930b61253bbee2dc0cb2580449c234979733739d60b1e4c250cf38460240ddd8de171da0e790404c64d73d02d42540bb35b99bb9ef2d51af633c8546ed8eefd7a47cca204d3e6a2a82a6a661940e40995de3068033e12ad259c9a05af8b88196215be9a4310fa41e88454d8037572147571482cb0ffd39d50d1b09c2a68ae8a5694842bc8f9104104b65969eee42a43680a763fb577b0811d4b03d04c5060521b569d253014832d66cbb2163b1a15d5dc395969d47a) +emitted operations + +big_map diff + + +storage + (Some 0x0192202a64ffc9df0023d8b9b7125fb5b889386ea4e421bd8a113b1ebe45f491ecf552369e0e9e297d75264e73f5ac29119347d4871f1452d0375b4a19eaec758c58f6066bdc7c804ac9bab38b61f475913d0b1e80d8eb00790a11cd5ba3b81001069862fe6de4183f916099da7b8cfffdea73965df644dbb21fe2c9036296b01506fbd8299a8dce20c185f12a864e6c0f3c2e18a2e79a922a5f8bc59f48a4cd8ef322c678f080a10c4585c27af5c3bcb38a19f10c83ac484d81b55eb1393dd7) +emitted operations + +big_map diff + + +storage + (Some 0x1251e8448175157c4d2856be19064bf584481dfda30cae0d0b6f1e33b2a335be1a02dba175aec178718db6dc67409e8d09ae2872ec0d74b84c4a6eba82024630c290c6da27f387b39abe0f4fef1e1879bd17d32b1712cd9c2fa59c42796a6beb0f820092b9a5722b03aaf53470ead23b1d1c0a2263f2f010a5872d0251a81e21c21f4900aad8cad4f5615a9f9966e1090b13b49d84b63a6480c608dde86c383c6c943ca211d57b11aa4d518ef81121fa2604c2e650998138942d892fd49c258b) +emitted operations + +big_map diff + + +storage + (Some 0x05d336c2765803c6cb4b385ab9d4f4fa1ce2da0e5efd59a1fff5367678e6620664406da388d05b3b448be22281b2b3460f0c2b3b46ef2845bb1bf11ca2909f321cc35a295c656d7f0a432c31d6ff82b62cebfe000324d5bd35dfcff4016e526d0c424b33f830246ebca7fc52d1843d93275265da2bb6edb6edf6b9a0ff928cbb621aaa0c274614b185e39f3b8a91e50a13c54002d7842ba912b15f0671bc8e10bee8c8cd6f219f7115d9ed6d259cd029e75fc00ddb4cb508841b3c4ffe383d31) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_random[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_random[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..28f64202bcb9351704b6315ed535808e40475970 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_random[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_random_random[Fr] + +storage + (Some 0xb33a7eba53cdefc6ad9cb5c1328402d360c44984ea5dc51c2f542faadc6be816) +emitted operations + +big_map diff + + +storage + (Some 0xd3c6ed5a38abf39effe32bb89f2750a7792d10533191c9e7c24c4a110e918462) +emitted operations + +big_map diff + + +storage + (Some 0x712b1fcd10c384804b22abbcd62dbf10434baf60e33078f349b47a245a99394f) +emitted operations + +big_map diff + + +storage + (Some 0xc2a04fd112a74a4c60193a518a7a2dd968e63c4f122c5ccda2842e30040a1d0a) +emitted operations + +big_map diff + + +storage + (Some 0x145e33354dccac366850661cd8dc6b08f69edcd424055700833440bd798c1f1e) +emitted operations + +big_map diff + + +storage + (Some 0x9add5ab74ffe4b42e3618c846e60ea2b8a785d5b9392762ede89f50c85ff7803) +emitted operations + +big_map diff + + +storage + (Some 0x90827b0e55cd078db382a78e437a2320adeaf00847ad95a6c920ef2a13954727) +emitted operations + +big_map diff + + +storage + (Some 0x5bb1c6b970d42235a163ce608b783311e47114fd2d755624d9ec2c416d09250a) +emitted operations + +big_map diff + + +storage + (Some 0x3c32dff99dd4798310d347d73dcd51055acb344aca9135fd75a5b5be45ac8221) +emitted operations + +big_map diff + + +storage + (Some 0x8951db6a4a847740ee7a89d7e4057e2ba8e0fa5fbd8a6989c99f204492765e3b) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_random[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_random[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..64f272a2e037e6f156fc97f3391198af4a529c7a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_random[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_random_random[G1] + +storage + (Some 0x04e31b8535d081c6216917afc0b998284a19efb004598e40af32cf07a7c01baacb96621f42800d560e7bbc1cd76ef211046404a2303e2df0f827efee06a0146a3cf18a213b890080e33478eb652c142191363cec93bfe88f0f29ee65cd8a45a3) +emitted operations + +big_map diff + + +storage + (Some 0x158932735210b3c07f9c15eedec8acccefe84d080d3d5e06795e6ea3383e34a57c8ed1c091b6990d636dc3dc6e2b0a03077fb11f6c64d76840c168238b5838d2f06a27d48b1bd95cfd43b68f0a5871d22df1117b398118e71379602ee7a98e08) +emitted operations + +big_map diff + + +storage + (Some 0x0a32114ba43665abeb4ddb111a262bcd7ef8aab2f628627a4e237dea512835b4c8f7d3ed3bb2c4f8c99d68cff26b138519da6ab3ef7d260c2dbf7e84cb65890d65df014911b2d3f6d6e4248a23f36add20fc3c27c93560959c366a408ea38847) +emitted operations + +big_map diff + + +storage + (Some 0x14512db2530c824ca00345cc815036ad2a6e9d048c7571c74aff33f9f6b3a54239a893ac73142f3e0c74a5d179c0c5b2010a163762468c6feb4d27f1abccc4cf3fca36ce15868737320bff7aa4294bde62d103155e63b74de46d06d6b06ee1fd) +emitted operations + +big_map diff + + +storage + (Some 0x0e4459b6675e6b703556b06bc3db6adf195e4a0e3262bb12fa82fdbbb41d6aa0620743ed337ee87654fa8a22d907847b0d0c3e578ef5c00e360dba8567b12e4f3ecad77a2bdb303888af1c2fd730f5bdcbccfb4ad50e8571a0da0db8d7f63227) +emitted operations + +big_map diff + + +storage + (Some 0x0f32aa210d52283f4495ca85ce595df832cfa90d212922afe466a3d58203d419fa6cac2bc33fe2ef42c684c97ea061f90f49309180a9238b366642cc78ff5bd4ee8ee82aee112368248ec1a13d36210649b5696528e64a16e04f7c52ee14fd8c) +emitted operations + +big_map diff + + +storage + (Some 0x1658a9b3195f1103234c8115a54afd9455751a59223922cfb3b2c680be32511087f3ae762616d843fbfa19096fd58d990d6b9ddff4af5bcdfd44e7f49ed23393bf466a82b3e8e2281d883c6ccf8708755add7581a6a90f19be9263d8d624266b) +emitted operations + +big_map diff + + +storage + (Some 0x0182e82dbcb3151a65e424f9d5962e652eecf163a5a06ef5dcf1835009cd2cc0106b125bc6187a3eabaa25a8c4ef5c5b1009427ce8cf6efc38cdbd6efeb6c5463cd5d508fcf28bd7bd2c7eaf90b29bdc49cdde479a6c64bfb086d023972bb0f5) +emitted operations + +big_map diff + + +storage + (Some 0x130144b4bf38c092a5239371271624d48cbe36a0461feece232015f64917f2bec1bcba8e57597932d2a2776e2288b0e3068a74d96f52781b2b11a40ae730c56d909b6aa82afe81f291ba17667f8def0c8c62cf75b800d42460e5f1956eee18e9) +emitted operations + +big_map diff + + +storage + (Some 0x00f309e7224d4e6d1c59e27e2f651300d9bbb17f58ccf23943d88c7a4ada9902779c3d92a701e419cbf2e719927d94ac106420f6c2c79cc43631033d59ea62663c1c4eb127c43806a2b9d0e34bebca1ade68fefc795913823724a74a15df6a76) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_random[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_random[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..bd38f74e1971656d53b176d958043a6df2618a83 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_random[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_random_random[G2] + +storage + (Some 0x0b2d5f882010f2406dd4fdda47ed2dce0a7419de3ce13360c709d420955d8fd254c0369250de38a69484f3d42266e56a0df6a9f48674db24a8adc43947f4d4155059769fda12b7de6de9c7d70166c3aa3b5780b3ef4e6285860935c5025a48a70ddb77c5df41cc6653f5ef1edf35776fd7f926e303115c1eca0465ab524626e16095d2d1bd516bf2bfc2ab4bb39c968c03bbda48f947a526fe887442e9cfd9dba4ac84be8f8d03308b9f32d566289a6cbfe19a87b13f87c3220bde5223f13568) +emitted operations + +big_map diff + + +storage + (Some 0x1170918e77a35dfc20db737834c50807efd778b7f0371e0a5cc5621df21f45311fc7d2cf36fa244a15605ac94f9bb12d0002517d54651966d9159aebc372ff2a7deec9a0d7dc80bce22025ace6cc1a32b8165e89790a8d6205121eb00238782709157dd20f2755c12822abc330be0b4a72df19d04d71f8cbd0357de1af8336987fd5db4f91f8813e66ded7570255c2fb11a13ba75e65187d7f342d7b4ef3ab41778bbd01f42680c86488bd7864cb78d9326e2e69f7195fd2fd09e06cffcce84d) +emitted operations + +big_map diff + + +storage + (Some 0x13d581984d95ad0ccedc521ee63077dfbfd3570ddf8dc0372f7411b903ce87caf5fc8a1cb1f66762e267a48f46a488ff1610ef168e28b79c9ab047ac9707de363b1ef06fb5ad86d919acadb9a6bca419d05dd129bc7436d4a8f024d4bdf7af8c0b1342fe8a6e949a51bb0901116d89437e7e18b8a40fb4be11f447879fb2651f7d449d70f84a1f959cc42869a85fe608062802296c3fe013f46b28c458ba28651c70fb61056b9a6af6b947e80becb252040dc8fc2fa9c79478973118d0984fda) +emitted operations + +big_map diff + + +storage + (Some 0x065e2a7e8b6ce16f9d46bfefa994cd13fa6813f6bad47e1d792dfd2e9bb4c3449cd7ebb05a8fb6b82b49116ca0dfb8a4041d960f46a4b0ac4bfe755470dff54f7b4d5bcb4f4d52ccf520b3f7e5defd6e6eac7b09f09f0e429c27477d5ec3a12706ad589e303bbed584d1ce39479c7a709bd73d4cc204ba78b7f4d70927a17d61dcd8e10e3359f396f98509f3b63cb16a06b68abc4b9597262f73f181bf042ef5c79b97c40304c259034534b3716d8168bf975565beea7f1ea21bfee63140d7db) +emitted operations + +big_map diff + + +storage + (Some 0x0c886b3d45067177888373985b7ad9e01f50fa934a67021f917ffe8a4f5730885c490f312bcb74590609a0550b26985711c932d4b30f82101a6b058f27b41edc2374273063470c3015840a9074c433cff7008f7c237bca62eac80cf82408ac85147a01f835601cb405e7a5daafb481462de4f5e765821c5e9c24d79945ffeb9926bcb5c516b1be62474f152fdcd79a7318f5733f19908cb27a4339c7cec46d2e904026ec421f41935ac05ee52dcd32ddf957d36da0478a231483cee910e158e9) +emitted operations + +big_map diff + + +storage + (Some 0x016720c0b2c7541ade5089d83b25c42eb26f76120904edf5d48c12a654df5bc690f3b8274f9a13b471e9d3397b253d5b0070d7e75316b1fe6581e120becefae1963f2c02e3dbe78fccaa0e82f3dc6b26b0f8fc878ccee3aca8681570864732791521735b6585f5543059a43e88d2293b372e76838962fcef28d9063259fcd7dc6216c833ad99fa0cd83c7aba57176da20a8a10c28d40cb495a3b4a7bfdddaa5b721a85b9dcb606bda5763eab6faea0ebceb638af2b2d8c61fa35c7e22d0393f3) +emitted operations + +big_map diff + + +storage + (Some 0x00971061214085d6e490b4e543696d4e2a5da1d7e3593bbb04444ffbc824a8f9bd9273b0a75f9672e5ef75407dc4daa503ebd0198f1af03f5d49688de7c9864836a521b93804a442d582b103d2ce3acf805ab611ed00d94eafe205fee48b1cc808c738a923f793e75b4a3070be1cc70d25eea3939703cddd1490f0f518d0cdcdcd7942b294020cd26338a25d3d8a2ddd02988eec1b3a4bbe0e13b6508b5a3bf790ff8ae7c78fc5ecd3760c7be57e94decf97f0271e7ef0c7396133b2b8927441) +emitted operations + +big_map diff + + +storage + (Some 0x17a0f51a199054d24bf00e707680a5318740b1e0f60935ae262a04a2e6a965d78ca4b066c8810c1c4ece3ba054b4f706132145795844cc04aba7fe5b92af3010c7d2ea264d82257de9caa012d267d5d2f040204d3a9b162ff35d58a94171a1dd0a6bf8ecae4b6109dca88a2bb07a4f2aff9148cb1d5af227278cafdc4a482070df87bd7cb968efafc621bd9fc0019e1114dd78975957c315f8f0988093457cbd710ba31b0f9eeda8b8d78e9d5833037ccb4a729726c3bb14941344aac882b9f1) +emitted operations + +big_map diff + + +storage + (Some 0x19d4f927fb96db848401d650a01ad72d05be245d7d75dc7e670e054e450e59b4c57119c8ba3df43e36ed405553a3439e13d903d0d8644031b13e46030ca2cd9f1450ac1428b54b399db96ed24f3d017a97bf5509470689b7585fdd848c587bc30f2c4d9df0e3b88e7d70a1288dddbc86e9c1f17cc110ea1a84f6900287a6a6ee016f59e02129792808721cee006337cb16657108891cb67ffdb6a5fd6fe4b5160cac312ca16aafd01ad9352a69b9e5ed2fdcbd58624fa800dcf0af4f6afc6cac) +emitted operations + +big_map diff + + +storage + (Some 0x0d4c4a2a8095869ea61b83d864cf7ad2611aeae6d8f2c980e8646e3cf101ebcc53ec086effeff6e79b97c09cd9e49b5719b698cb3540859837103da3bba5f89814a66a4bde5b6b8e12a585cefef8a2b884bb38e4dba52c3dccbe775291f971d41177f7ed1a9360fbc3ab6227d0f71a11dfd2a44f8e7d6fc4e8f42ad1e10bb1bdb3868595beddefd15f75c45fa857bbdb05955023d97e7360438d8588415ee12a626d8c0e147e9de1ccf2ded3e2826e5ebd9f48ca19fdd8b12c98dc6c8da4c951) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_zero[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_zero[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..c0514ea536865d5954f1307ceb2a61919945f7c3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_zero[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_random_zero[Fr] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_zero[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_zero[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..65d9129f8d17af6f51dc8460ed914da6c89cb0e9 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_zero[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_random_zero[G1] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_zero[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_zero[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..25778d9cd2143bfe20bc4f22fc1a8691f5d8727a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_random_zero[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_random_zero[G2] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_one[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_one[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..c12088e6d76bdac24dab743ad7cfb182f7b09b93 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_one[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_zero_one[Fr] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_one[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_one[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..a8456223204ad36b10295a94f39cbacab7283d87 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_one[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_zero_one[G1] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_one[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_one[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..cd7191a9c0b18770ec38949494f3ad70e5609b91 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_one[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_zero_one[G2] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_random[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_random[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..efcf478a95fbd2a4d455961ca52280f8a4121afc --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_random[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_zero_random[Fr] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_random[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_random[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..c7bfc9b0c537c5c4d758d0f74417c9f763d620c5 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_random[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_zero_random[G1] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_random[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_random[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..3d08d1a349fce66addb2738333be06044121cf20 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_random[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_zero_random[G2] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_zero[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_zero[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..7f902e9a0f5001a7e3c13b6f69b133731a14e33d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_zero[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_zero_zero[Fr] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_zero[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_zero[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..8e265414d5e660be317039b22c4cd525eecc86fe --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_zero[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_zero_zero[G1] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_zero[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_zero[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..a9647167a06dc9ea5bfce6078d0ca0a075a2eec9 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_mul_zero_zero[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_mul_zero_zero[G2] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_one[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_one[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..090b92b7ba2a256a39770e93468d0e91608857e6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_one[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_neg_one[Fr] + +storage + (Some 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_one[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_one[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..7524a87c9bdd28a4448a8cbdcc839ede2f7fedac --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_one[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_neg_one[G1] + +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_one[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_one[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..1a7bbbebdc5e178d7ead9fe9ff9bbff550bc29bf --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_one[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_neg_one[G2] + +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_random[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_random[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..391834589a98d98bd4bb6aae41a107c10b2ac394 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_random[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_neg_random[Fr] + +storage + (Some 0x9ac69bc1db5f20d9044178b065f5a09c8442bae11c45371f325e816bf721d739) +emitted operations + +big_map diff + + +storage + (Some 0x24a3fec4e7f8ad2ed4b6b0284e5d03ad143f3ac4d0ef3aed1f302c3459823c59) +emitted operations + +big_map diff + + +storage + (Some 0x0dd533bc546e5dcc64ac9d74ef41109f23d374ad2885194873e582d7700d0d16) +emitted operations + +big_map diff + + +storage + (Some 0xc0f43e2aff39fa4bcf5319a48396587b076d0193d9a1c31b676614d9b6a2dc0d) +emitted operations + +big_map diff + + +storage + (Some 0xbf12217bfe47d2f1d96db15e3f4a8eb9ba1229c610e2c0ca85205e217fe44422) +emitted operations + +big_map diff + + +storage + (Some 0x5b33082c052de9699109edb03ca4961ccdce7dc0b21f35ffa208f0c380d47353) +emitted operations + +big_map diff + + +storage + (Some 0x56bd703658653401c10d85274f305dec559e9630f202e307dfa3bb3980829360) +emitted operations + +big_map diff + + +storage + (Some 0x8b7fa597cd2d60533467ba57c1a15029a40239dd4cbf50341e7eb8aaa53abf4f) +emitted operations + +big_map diff + + +storage + (Some 0xcf62b00037ebd1ad24ffc51831e12878fdd817915f3bfc1f23150099fb2fb81e) +emitted operations + +big_map diff + + +storage + (Some 0x41df1100e72effd309b1f30f51729681df099140be3fbeeebf55468b9cb35d22) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_random[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_random[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..94611d98b4de4a309fb950761b72033c2e57991a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_random[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_neg_random[G1] + +storage + (Some 0x197eab592fb38019ed2b362a048af848d1cc13b4a6c1d035f0dec4f5c461df58ddc92c9b6cab42fe3683000d91ceafe418d5a984c5833a305e02b18372d56e0b3943e34fc5aa2e79dcc359d8a299928b43bec4667443ab008dc91432a9e81ae1) +emitted operations + +big_map diff + + +storage + (Some 0x15d02840b69f06135d0fb3b82ae94649b2a10da9f7b4a5df7365c95b9d04c755a863ff2010332a8cf2609e08578ff02a05d1699ce8d778f3d2d7aa3841ec11e23682ab0e7933b43d8bd7e8e2c3b0dc5bb3878d7c0f01fcdc2b4e97f84c46472c) +emitted operations + +big_map diff + + +storage + (Some 0x14f7f5b6207b770382e65ebe91981942bc7c88908d1b2e73c6ee1322300f703877064d65d16493a3a9c3e6c45b049dfc0166df18d9caa4a3ba208d1ec549ea8cd27dccb7e22497594b4981ad758393a96de9be4247b185d8117774616032a403) +emitted operations + +big_map diff + + +storage + (Some 0x19b7acfd822ce85763c2d9e81425e571397c506ee31a5ae31c44fad5288bf3ca43c1abf6e78d380f0f75dcb83e1ec9cd17edeaaadb33ca8c4640da22fbb6733c5c11cd77bffc1a8e900399f6ea807bdda382b5173ee95ccb8807f52923a4297f) +emitted operations + +big_map diff + + +storage + (Some 0x16a404c56efceca50db3014d9c764842f6cd2221ff6b89605bc617b48a12e791e01c089489a5cfcf8f02956dcf8d2d8b015b9061f8f854b00f95fd177a0e9d8254b9dcb23e486a2ed13a79cf4f2fb430cf3d1c1eb727909712cc71e780226728) +emitted operations + +big_map diff + + +storage + (Some 0x03fd56e83ffaec3a3441bdcd46ad961f62819e72e9aeadb78b830a271c4d480014215b337fc7fcca3a7a6c9e57b62ed909c0dc635400cf2268eb1b1c841ca68e5cdb7edbba2a388714319740348180b33795377af9228b13035cdb4bbfa5bb60) +emitted operations + +big_map diff + + +storage + (Some 0x0a31c603358cc5f0536c3b4cc7bb8ed1a6e0da1113eb42a13a07201f071f69f84fdab55bfcf3791495317a9826e0a9ca07ea3e8155f0c3a0df59c86120a0decf70bfd0886be8433932dfb62e7eaabb68da56859be8c78fe0efe6d774fbf2ca1b) +emitted operations + +big_map diff + + +storage + (Some 0x0b2b25da57dfdbcd47c80f821d732052e890661fec1b1a89e2bf83b1bfcc0f0c59fa59be2eea602692472819aa581cc319742355a5c737fb173d6fd2b53772de1fb90859d39fc6d9d64528be91b41230dccef41eb8af2e228d73bf80ce152dea) +emitted operations + +big_map diff + + +storage + (Some 0x072cfea08d58f5fc8db45c45c7ac6fcc01a0279b33652a685e1e961c2385b307ef336ff7a7529008158388ec3342a3980b0ffd641f1319835631e7e4c72450900c2d4cfc9ca2a9427189047b4d84ce7cb21148b414f1a160efa4b069c0a884ca) +emitted operations + +big_map diff + + +storage + (Some 0x12d6f85f33ad5cf0c0fc2c77c79bb7ac152b065cbdafbb7ae9b190ef16f3f3ba07a1a7be5af71e80038b843fc6d9772612da90cb178d7a6b48bc95b33cc431168d84bb441364c1df012faa8b53fa7b602d2a961fb65a8e13d37cc4e1d417b8d8) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_random[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_random[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..07f8b52e9a16fe78a93a599c902c3889bbe5f414 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_random[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_neg_random[G2] + +storage + (Some 0x04c4113c5de4461ee1effcfc208bb5a9804748c180af325b70966de7c379381de993a4659457b37367c9284ebf914033072014d5e51b7a11f6ceecdf68e310399700d00cd49696797fd39a95e701043291aa570cc853a3fc98389428112e62e90827091bae55288eddb843baa59bbbae59aeefc2e92d212a062dca9e1e96d621c4fae7cd94b1abab9b6efcbc720723b60ddfba8ba68bc874a1aab91b5fa6c6cb36a5cec01fb27b513a87c84ee21f18badc394467093a111040da3175c968157c) +emitted operations + +big_map diff + + +storage + (Some 0x19bf6c44cbd63175794a5730a440de20c66d93c2955412f40501117770de06ca62ac213b332dabafc32fb535c27c734d11d897534063baba835363bc6c8bb52d436d0cd6d3b7d80aae8f412960c6e31938b4c8b361ed3452dcf3fcc5021475dd02b7a90965f4ff09880874e59b382e0c1b37619a6f1320a124cf55b36b3aa716e42a588ae6f01af4364d08e3c0d814ef0d02bbeb23ef4c23f4b145aef8a73bb1ffc4895bafccfc86e621c05afbd218cdd3c2fc69268dc8a16129194a72c606c7) +emitted operations + +big_map diff + + +storage + (Some 0x11f4ea2b3cd84230f43e085ae38a0c60d712486564ce5eabf2de3df5f0da8d891657ce1f0c9fcf016b9aff1f48bc583d12ced40a391db04687b45de84f4a59eeef3c3db75ad8862c4241d03dd0bf36ff855156a58f185234bef6ec7301826f8c00b0f31e6a7c2c87eb9866c0259cf5b30997a7ea4513a70edc430c2e201822a3cea3bf3e0d2ad17680036d3423f2db7f132866d134609c331dc4aa1caf0caef348c51633e789f152b6cc255a8fc426c27331b519eb0cefd05b08bd23c2db1aba) +emitted operations + +big_map diff + + +storage + (Some 0x08968210984e1431183676214a406cb925239d7eb1334a07bae001019419d0f41ade7163bcf5578b7b7cea9c9efa12ca0dced010adea7a72bce2be7f2dee13be641ee209b87fb4ae77b00b43f30f770f6c745e9d4617d22020d5686ae40a495219db215c85c3166e233a2027314f1c3807aca9e90315a9dd0da624a87c61c709e2fad9b800290ebddbb413f5655ebb6b01008c500234652c966f668524577ddd3268ba1934d0eb44171fb2d2c8f24c21ff1edc3a68473604e2660646de8fe01a) +emitted operations + +big_map diff + + +storage + (Some 0x04d151207587d306af535541cd193cfc0f0039e84155c78bf9b0e5ef4b61f6cc49f39f9e84ed48c7c9b04c6e78dfc4b317fadc38e9900aefc0ff618ff983eb713861d8ff8cd0af5a9445f0cad43bef39ed4e0855072b8dae4ccec6f6ae7e1a62134d156f2cd1587df87ae54cbb3a6de862dbda2c898cc94e93833a573380d3af53d17061668c6693264cb124c87ab2050c9ecf6526f6401055724eb2fcb5173453c77870eedb8f774a711b8b75d0e7308c8e1aa3acda6466c48f148dbe04d1ad) +emitted operations + +big_map diff + + +storage + (Some 0x0c430e8fe9556cc97d2b00a6d84ae91f4eabd287e8a9ab9fb158b80eae7b000109f5ef7dd5d1efc9b7de64077041337110cdaa2bb05c7dbd6751bcdb6ade70100794d1a0ef3d462ae7e6a969a83e9f81245d389810da2e3ba8993ef7daff017005b222f1c29db487aac92aab1068afda51cd1e5489fc8931d2d9bdc142db5cccc17c65f729a57cf0ef7e4af9449f77000f39713ef371664621e2ad89f7c0261f4415dee34a6fe7c8dd041257bd2b793745d70103be171d0326cdc0321487d37d) +emitted operations + +big_map diff + + +storage + (Some 0x093485ee7701aefb89433f119a5b8d5a4230dabdafe8e55f26b23190b8550a1c51aa83ea1939d33de5477a4599f5101d0b36aa79caab813b87e102a83105b6bdb892e2381578aad742e53293c9bd24463156ca976342cbd03059b174e811884207b155b1dfc641bb0180493fcf47ed39010fd2d8420098b6ce5c1378cd402f725e7a91ee74cf068e4111a76ebdd2e6030b0220df748b9882f8f17cfbd1e624341262073563e037281c86eb70212e399c5efe102e9b0ba01f0b89ef266cb37cf9) +emitted operations + +big_map diff + + +storage + (Some 0x19428930e5a0f05f3319c7f034baf62b00cabd1568cff58065f30046b90021873cf56360730fefba5f2930d9d661dcb5034274f468bd901fed787268a0abaf18641ff90df4651d82e5c6d8c76af87032a8ff6e6e8b1a7bf2965e6f23cf0da586112cd75db7d04b7ed070d16a4372f0520b1c06a995af83d4389b418b8c026f2f3ddbe2ff6d0d8430a61b9b7cce9ff9d7196e415e4390bab69c57f39392dc448df55ea15f576492d15d046904d49e634a03809ccb1873ec89f23e95753c335495) +emitted operations + +big_map diff + + +storage + (Some 0x17692241047f40181fc0ea3d78c9c576477c5c2bef94dc7e795a1f06a32278f59ee4a862338c8d91093336652ea979e20595946083e9500ad695371dd38a84d3782f9bd1362c22210abff64e461b6f0dd6480f5af62ad72f6501a3b1cd5cd36215eec26a3f41f51d8066b88cf6882651b9a90fab9858e91e8cbb4231cc523aa5d031ba95123bc6a5f8e4b2f52fff5b650a81e87155d9e039f6aa9807a4ff68e91c61fc0b80d10e28ffda4e1f088079926575b35ef7f776cb0f36648066765c01) +emitted operations + +big_map diff + + +storage + (Some 0x1541b770bc7b492490eba70ec85bdc68ca78eb22e4f67bfabdf84ee7769e615efde8e6bd754d03ec62c41583b0bef01d06ff063375db383cf814f3807a5127afd82f55bf157bba04e36399cbaf189f63da12d29b0c584833d55b6e788e27d4a5176635964576c34bc77e17c29ffd8cad66a2b14880bfb03f5fbef5a66152617a093935ceca865ff6115b04a3720316db0b0b49aecb7883f2700551b8b1f632d7d6dbb1b2a4777c8745300a152eb4b46c742d08df7e8f99715df3a561c233ef00) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_zero[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_zero[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..e710163d83ab5076baebd40eec1970667a80bf37 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_zero[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_neg_zero[Fr] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_zero[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_zero[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..de08821030c793b8345b60c19ff719d204ea5e7f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_zero[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_neg_zero[G1] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_zero[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_zero[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..cffa0ffb9dd5b4d712ac8b94a9369f17da163e6a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_neg_zero[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_neg_zero[G2] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_neg_g1.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_neg_g1.out new file mode 100644 index 0000000000000000000000000000000000000000..400cff26ab83ffd47b893042b0877a537f75c832 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_neg_g1.out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_neg_g1 + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_neg_g2.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_neg_g2.out new file mode 100644 index 0000000000000000000000000000000000000000..a6133c4f4b129fe7da17de8be98c6b6b5e76c9c8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_neg_g2.out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_neg_g2 + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_nil.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_nil.out new file mode 100644 index 0000000000000000000000000000000000000000..237268fc902477d73ee3cfa29cbf6db0b7ce689b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_nil.out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_nil + +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_one_one.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_one_one.out new file mode 100644 index 0000000000000000000000000000000000000000..8329cc33dbad86659cac7e09a182a4607c9e51ed --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_one_one.out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_one_one + +storage + (Some False) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_one_random.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_one_random.out new file mode 100644 index 0000000000000000000000000000000000000000..17da03fdb0e417a19bcb52f25d2557f7a6729e49 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_one_random.out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_one_random + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_one_zero.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_one_zero.out new file mode 100644 index 0000000000000000000000000000000000000000..985298826117b953a0752108e7766034405e0657 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_one_zero.out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_one_zero + +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_random_one.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_random_one.out new file mode 100644 index 0000000000000000000000000000000000000000..62fecd1d664777604556e4a5b8f25a78cae08481 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_random_one.out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_random_one + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_random_random.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_random_random.out new file mode 100644 index 0000000000000000000000000000000000000000..6dbc0b94f73267a5bff0a84843a1deafee3e9075 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_random_random.out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_random_random + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + +storage + (Some False) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_random_zero.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_random_zero.out new file mode 100644 index 0000000000000000000000000000000000000000..caefc830d0e3ad3e2ee9d904e79c2a6e88bfdacd --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_random_zero.out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_random_zero + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_zero_one.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_zero_one.out new file mode 100644 index 0000000000000000000000000000000000000000..ac8ab146d49037f24b305edbb29932cf80ec9dab --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_zero_one.out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_zero_one + +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_zero_random.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_zero_random.out new file mode 100644 index 0000000000000000000000000000000000000000..0e573f05868871b327b3b92e5eda9ab8cba416df --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_zero_random.out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_zero_random + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_zero_zero.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_zero_zero.out new file mode 100644 index 0000000000000000000000000000000000000000..b5ddcc0ce2726e93ce488c0da310cf2964a1408c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_pairing_zero_zero.out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_pairing_zero_zero + +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_signature_aggregation.out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_signature_aggregation.out new file mode 100644 index 0000000000000000000000000000000000000000..718ad396cd09edd9861935d306c3bdcfe4ba26d9 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_signature_aggregation.out @@ -0,0 +1,142 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_signature_aggregation + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_one[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_one[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..779464805c784bb6290cc0de3f7a1b026152485d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_one[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_store_one[Fr] + +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_one[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_one[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..198b7817ba990c8354f861ef7b40f6a7ffb72a52 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_one[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_store_one[G1] + +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_one[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_one[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..c974ea790ad65300fd2206ddae192b9b4d6087de --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_one[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_store_one[G2] + +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_random[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_random[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..8307763d0f2c91472b8fb80178997c98773828dd --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_random[Fr].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_store_random[Fr] + +storage + (Some 0x4fa3eebe8eb999919b25e9496a740ba7e3db1e6af6d7dfc4226af5b7ff1bb31a) +emitted operations + +big_map diff + + +storage + (Some 0xeb3b4692c6d5d3be4529f58dc95561395d4fb06a4b56d5ecee427cb769df650c) +emitted operations + +big_map diff + + +storage + (Some 0x0fd278b6ab93ce8d6b66643b0173fd4e80d0d1776d0de34b13b6ff24227bae29) +emitted operations + +big_map diff + + +storage + (Some 0x9a6bc10fb59d3d43dd642524ddeb3f901c185488da989078efbd0166b878a66b) +emitted operations + +big_map diff + + +storage + (Some 0xd2e244946f6aa1a9f2e36a9f83faf915dd94d7fb31b1a4642eb7bb73861d0a58) +emitted operations + +big_map diff + + +storage + (Some 0xce66a6b5c6d97c52c44f3430271d6c466b1c9f656d43a3f6db6fb76a77b56d02) +emitted operations + +big_map diff + + +storage + (Some 0xfb437df580e072dbc887e9e0546c0843ccdc7b31264730e8e2f3c341a2d13908) +emitted operations + +big_map diff + + +storage + (Some 0xa1d61bc7847d649c7ed6bfdb0511393e83e6a8fe6a8999748ea767f44e2bca11) +emitted operations + +big_map diff + + +storage + (Some 0x5839a13cbc9d2ab02bba8d95197a7145d30d49b05c809ecf226e3e10a5181e02) +emitted operations + +big_map diff + + +storage + (Some 0x90348d02274bba201f5cb5a914c73410d7b34f5bbe090b3cfbe92ae307709055) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_random[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_random[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..3ac40e287be9b4fd42d6c29434fcad935345d1b1 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_random[G1].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_store_random[G1] + +storage + (Some 0x18782e3fbbe1f7abb5e2021b79bce810b5e8ae950c1e60d41731f0ae2ee4ebacbe59a9837bc34d5c61896561b04002be1760374bfa91e105077c507da80c080fe3a6c0ed820ce2515535f339b3f1510016ad6da0ff1a277065798e11aec2f74d) +emitted operations + +big_map diff + + +storage + (Some 0x1054b960d67ee71da9b596e7c543faf72544ba1ea2bc24d635f3da62feeeab2d0b00a8fed7ecf450767e1fdf1f2a913c127c6632387c6b5364a82dd2ff346b93cd29555913377b887c32e5a58fa37a7e69d1d82065e8b84865fee75aca361e6a) +emitted operations + +big_map diff + + +storage + (Some 0x0dbd1f474d065640ee4bde569142e26f7101a5c339c2f6630db6201c47483ed1303637aacb90002e1d7e7a84804b126205a8189fa87963e0fc81ea9c63e0a288768689f0ebe0868d98e9bb7e975026876f1df8502c6340adb3fde872f308704c) +emitted operations + +big_map diff + + +storage + (Some 0x141bebcd3a9c4145dcf836d368618d106cb3ab96669cce51cda04944eb3e0f07f0151a6fb4ba31d395692d4a305d623818a95f330d82b398d85782eb3a2793e098078058a289d5c5903cb78541807339db47e47d7dbbf2b5b4f0b6f9af323626) +emitted operations + +big_map diff + + +storage + (Some 0x088dcd93944d3cd43068b322488e178dd56f0ac3572d535d2c2d1da410e27572e425a4fcbbb8e10836f88d4010dba4a105a5ba71e19fc20bc6054df060a52887551b7b81196d63a3572c080705e9598e20cf3319343940de851d3d7ead06e8e9) +emitted operations + +big_map diff + + +storage + (Some 0x14c66800599dae815074aecfc36e2d43e2cdcf0c6663d9a0ab082488230ed0f6af46976598062df148d8b96144f55c5210e252370e812f951b90cc9765edbd2db2ba8157590338b3f5717a1bed450453f2674e3502bc95b2a8808e6d7442eada) +emitted operations + +big_map diff + + +storage + (Some 0x172318134285db82ebf7eab40d471dd4f733c0a624b360d8df00305ed381f3d59c7a54ce3996be88a63ce593a01c66e813ddee3711dca2ff243ea1e7141de5aec0a7611e67fa1f9c0e89ce7145ce58d0eef987d8949ad02d671166597d3a03ed) +emitted operations + +big_map diff + + +storage + (Some 0x0eb24546ddd153b1f2511c6155417c1d3fcc9750cb6b3af4367d01d485c2b6dba27cb1a7f19286e646e2f7a7aaf0363415735526cbb0f20f3d4141e6776f3c8b3255ee11ef05418ebfa62cf7e03220a5013a27e020544752260e295156f49c0a) +emitted operations + +big_map diff + + +storage + (Some 0x0e76d4b163d641ed1edbfdebdfa71c9fb6ad2e556e56ea0dadc3ea6bfc59b77e1e070063d9eb428b7730f35362310ac917e2386fd701b9389afb48d090552b8cb7a808aaec6669a06db758a7b30cf50933a275bac9a6e56ee4011fce86c496dd) +emitted operations + +big_map diff + + +storage + (Some 0x0a58dd111159092a784e404e0fbe2b03681a0c60ce1ebe52fea33f9780ac82118b6b8583b68fed0907adffdeef055d74120b04a2ebfd3a2a60a638cc4cd997090bb9b04d19cddcd61f9078903bd9f3e65fcdf9e5aec6de5a574ff7daef7cb079) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_random[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_random[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..4a626ad3a2191137ef1ec4590e5f3cdb7a1ed8af --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_random[G2].out @@ -0,0 +1,72 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_store_random[G2] + +storage + (Some 0x0fdb404adcca2b3e91f5b6824e6f3c88d0086605135f34e733a47749f72e941ea0a546307b76881a2735b6aa24d630a20b9c453f8be68c3a875c4623df2156e61419a83dec2945fab6a50256f03cc9beabfb209d91858be53ead266aff598280191da483f4545715b6bfed1f3bc1aed02f97ed2e92f5bd9818432d1a17c6cef0b738beacef691b40c48b310a3befb95c10e67239e6fdf04c5c6720107466f19bb4d21b06ec221b72cf1a0b6ec4c1657872af587ffdda647cb36f9d73089b83d5) +emitted operations + +big_map diff + + +storage + (Some 0x00ec703f53406268b162add4b534cafad633e6d9453d289aad5f00a7ac68e2a9b1d97e9fb3b622bd95597b62b1fa0e7211fc2a54d8fded35cd021de7396db9dc1bdadce1d940da9c0dfbc6883c1212c639f2982b0f8943fe08ec1a12f1ea03081326c959ac2d47e6f75eacdf604efaa784796cafa511ad560c73552b9db0f8c9e0b1c281163f05b5d86b6b939c8fa5f512f6352c990f48e11a057e748a9695ae1d277918be1aa8fab5c96df723c47825136ef09c36d562214c25a087a5667b39) +emitted operations + +big_map diff + + +storage + (Some 0x17100f69943b685b53113c589254c0b26b23808b376a6addffa896ef873147871a0194d077acce64254e667890048f18056a3208afc3295e0829902800cfa9fcf50edc78841749d02198a3946010e6d800bd36171d41dfb6d79988f61524136003db45da43b3825c6dcf8b9ef46c8a40c842fcc3fee4ccf6d119b7b643ead789612ba75fca0d0a16dd31be31658c7b1d122b6a32d75113bb900ccf4a4da9cefc69b23814c486c9ade79d82eaa0593167b14a06ea2158f9d7710318d82553f1c5) +emitted operations + +big_map diff + + +storage + (Some 0x039c8fa2998d6fd874ea7b5cdfa5089bbe4cddd9958b445b6f33f65c27fd47b56a911e8134fe620275e7feece2ba1f560f731c917b8f756ec340c9d213a14c0f04bc79488ad38ca088d96c9a1c899aabc6cbf5070abf3231394b917c428fb0c5148e4d6c75c3b64e614582fefd2ccc979767d4b4da262d9c95ab27cf2fdf500268f0de8ecce5dad0f8ff5a06ef0e270f0dafac5b9ee6c9ff6665954a58e7dc792a257c1d80f27c1f91f9dedf4efc8da6e1d69d445364c7b7c076aef189f594e7) +emitted operations + +big_map diff + + +storage + (Some 0x118f6abab59d71635a4206e8fd16212e6d2f5f7c756e4308505f9e6473002a198292be2c834ca70cb40a1abeb3989c820a94d180da0025992a5c5ce516a2fa84c2e66d772acaf71c990aecefe420f885823f55bfdfa13db98035ae41c06ee6dc1305555d6da8ba4a92fd9eda92934ac5aed6db9fcc925fa51193a0ddf04594f2707d680d710171f041222e14644debfd14f43b880a07bdca546ffd02d792ed38be37171971ff662b094d54a37816aff6efbb2e57875dd9af97dee97e8c5f6109) +emitted operations + +big_map diff + + +storage + (Some 0x11308b1d8c4cb3cb1a57c98f1163ea78c44c1035cbc741988dc56a3c10c3d3b94b29445eae3199073857dbe6b146d6aa087a91a83306c1cbbc1f2eef3d058639ceda4e98ab1124dbaccc52dd25d7116675de0ba740fe95f2700ec1504461365a08ff04b06bba77a77b5b7ffa45a3ec56c8626fb7219f0d2d891251c1b4881f141bbbaf09217044e9bb69c8c1652476500153567f2ca8dd517cbd1c3467c10771d02fbf45fdad811118b325ce97e43ef72beff8857f44b0968de7b01a770fddd0) +emitted operations + +big_map diff + + +storage + (Some 0x0172fab176d798aed92f6ac9abeb28c510d77fd42601522db72c8fd7abe52fa0ce5adfb2ef67739bc4fb64fbbe3cd52b12a54aa1af0a44cdcc5c9110c13eac553ff037f1a8f304d052a0fc96ea40c946d5d31a8427feb1249fec862c28356afc0794bfcdc71fb3dfcf664e9a8db201c5b774ec45c2f0028531ff6abd2292dc1856fa9420fc8f5b632e84a592d73b25ba0fbb3e8cc6371e5f0d6c04b356f0e9d786545619a397f1dc1041854b5bde626b1b1d01258d6b16a80588453996a6eb00) +emitted operations + +big_map diff + + +storage + (Some 0x0156d0250e60af2f0678224eed0afee0594bb6f85293f7c4ab93b17ea0231bc1590d28250968931b8ee23a6f0f364d8c029e81178b6e60e9de5f858d44b102b823a028c4b8c230cf78e5f8a77964fda2bc4cb1a8cafd08641dcb20689b0903c104e58754b4c52b2b225473b407544d32823b8a7b47b2b919b96da883e20bd8a526ffe21928186d36d8355c16aa56523004f6dc232f441b80a9efaedec4dfd3abafffa97af0623f434e324120ecf61516affd143cc275ebda8c7552c89c718764) +emitted operations + +big_map diff + + +storage + (Some 0x058b2dbf9ed4d328d9afa79262a86ef47a044bba9226441df410d255040ae88931ca92ad6f127656c2309a3f9724af830cdb406c0cf88f930976f2b162d300d58930a9ef86869073be0043e9383e5875d9f5ce8a2cfee895f2591b6a265811ca13baaa13b0d54995b9ac5c2bd893730b07abf2f8b4c99b121870227c594365dac3e330dbeff1c2fb93f8b1dc6ec4d8311525ee7f96ac8b71f94b149bde3749c2d03fb8494592daafb6963c6a9427b887d67b0ad72c29804aff97897e6272379b) +emitted operations + +big_map diff + + +storage + (Some 0x0cfe1a34585ccf7095a05262a23fa1acde77911d1b9d0f894d63457ae6da644c417569c14a4e39b0ee2e51926a1ce7f108d6d899a1e78d27e6586f31d50fdf882d001bdb7fe934061214b756c5a9e64b66b5b13cd4c44ba1dd97101e394f82ec0661b38d968d819b85eab59f321c42b2d05e8037f4d1ba00bcaa80f2fe8f4130c4e292c073a856e095cc823965ffe97918ef4fa0f24b9bfa56b0ce783b3a6362de2781080d6ff52651e6ff71176b873318138cade3d284921c3eacf1734f5854) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_zero[Fr].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_zero[Fr].out new file mode 100644 index 0000000000000000000000000000000000000000..dc47bbc7208e6b6099b09dcd7ce80b993e0f9ff9 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_zero[Fr].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_store_zero[Fr] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_zero[G1].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_zero[G1].out new file mode 100644 index 0000000000000000000000000000000000000000..babebdd74b30995bea248c27f8f9bc37e3b5f11a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_zero[G1].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_store_zero[G1] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_zero[G2].out b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_zero[G2].out new file mode 100644 index 0000000000000000000000000000000000000000..6cc46bd7f33ae96bf0f7f8cca6202b95ed659221 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_bls12_381.TestBls12_381::test_store_zero[G2].out @@ -0,0 +1,9 @@ +tests_009/test_contract_bls12_381.py::TestBls12_381::test_store_zero[G2] + +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..528f9a138cddd0a7a771c8dec3dcd7a83c3ce62f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert.tz].out @@ -0,0 +1,9 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert.tz] + +{ parameter bool ; + storage unit ; + code { CAR ; + { IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpeq.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpeq.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..43e8fc97abe8b1864934e265492ed57baaeb30d6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpeq.tz].out @@ -0,0 +1,12 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_cmpeq.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpge.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpge.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..52d70f10df2163fbdb73296eead41d5e47bd2f13 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpge.tz].out @@ -0,0 +1,12 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_cmpge.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; GE } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpgt.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpgt.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..774b8e2538fe85a3c82798c6a5b25ac40102a6ba --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpgt.tz].out @@ -0,0 +1,12 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_cmpgt.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; GT } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmple.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmple.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..d7c04d5a4d06d35207960511566c9537a72a94fd --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmple.tz].out @@ -0,0 +1,12 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_cmple.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; LE } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmplt.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmplt.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..5a019e7b66c75e377bdf4e97d5e0e8d41b24a106 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmplt.tz].out @@ -0,0 +1,12 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_cmplt.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; LT } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpneq.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpneq.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..8713a030cb80df6cdccf644898dbc5d9569608e3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_cmpneq.tz].out @@ -0,0 +1,12 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_cmpneq.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; NEQ } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_eq.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_eq.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..bd40abb27ed0f59a8e8e6d8a0c97ce30c25a94a6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_eq.tz].out @@ -0,0 +1,13 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_eq.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { EQ ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_ge.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_ge.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..c795883491f6d9f49655295ba8bfa53577389cc2 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_ge.tz].out @@ -0,0 +1,13 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_ge.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { GE ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_gt.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_gt.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..5f363f17f54e626ee34a3846c8708dd4328e8416 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_gt.tz].out @@ -0,0 +1,13 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_gt.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { GT ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_le.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_le.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..54f51cb2e22dec4b7213f8236f6031b627359505 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_le.tz].out @@ -0,0 +1,13 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_le.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { LE ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_lt.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_lt.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..3a578bb3eac9986c0eb89a4bfab822c7b221d47a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_lt.tz].out @@ -0,0 +1,13 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_lt.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { LT ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_neq.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_neq.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..2d3c27d049631a30c0ba8590a8d1b202fcf1ca26 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--assert_neq.tz].out @@ -0,0 +1,13 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/assert_neq.tz] + +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { NEQ ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--big_map_get_add.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--big_map_get_add.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..25711f62f38d254596be15da381ac416d8bc0932 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--big_map_get_add.tz].out @@ -0,0 +1,23 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/big_map_get_add.tz] + +{ parameter (pair (pair %set_pair int (option int)) (pair %check_pair int (option int))) ; + storage (pair (big_map int int) unit) ; + code { DUP ; + DIP { { CDR ; CAR } } ; + DUP ; + DIP { { CAR ; CDR } ; DUP ; CAR ; DIP { CDR } ; UPDATE ; DUP } ; + { CAR ; CDR } ; + DUP ; + CDR ; + DIP { CAR ; GET } ; + { IF_NONE + { { IF_NONE {} { { UNIT ; FAILWITH } } } } + { SWAP ; + { IF_NONE + { { UNIT ; FAILWITH } } + { { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } } } } } ; + UNIT ; + SWAP ; + PAIR ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--big_map_mem.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--big_map_mem.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..7506812fc665f82f6cd829771858b4a1eb6a5058 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--big_map_mem.tz].out @@ -0,0 +1,14 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/big_map_mem.tz] + +{ parameter (pair int bool) ; + storage (pair (big_map int unit) unit) ; + code { DUP ; + DUP ; + { CAR ; CDR } ; + DIP { { CAR ; CAR } ; DIP { { CDR ; CAR } ; DUP } ; MEM } ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + SWAP ; + PAIR ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--build_list.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--build_list.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..85df53c93f62d158f65f35ce0eef860b2da28663 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--build_list.tz].out @@ -0,0 +1,24 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/build_list.tz] + +{ parameter nat ; + storage (list nat) ; + code { CAR @counter ; + NIL @acc nat ; + SWAP ; + DUP @cmp_num ; + PUSH nat 0 ; + { COMPARE ; NEQ } ; + LOOP { DUP ; + DIP { SWAP } ; + CONS @acc ; + SWAP ; + PUSH nat 1 ; + SWAP ; + SUB @counter ; + DUP ; + DIP { ABS } ; + PUSH int 0 ; + { COMPARE ; NEQ } } ; + CONS ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--carn_and_cdrn.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--carn_and_cdrn.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..62db57f0df16bfa55ee2a5b59292bb1d04108575 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--carn_and_cdrn.tz].out @@ -0,0 +1,29 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/carn_and_cdrn.tz] + +{ parameter (pair nat nat nat unit) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + PUSH nat 1 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + { GET 1 } ; + PUSH nat 1 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + { GET 3 } ; + PUSH nat 4 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + { GET 5 } ; + PUSH nat 2 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + { GET 6 } ; + UNIT ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DROP ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--compare.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--compare.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..f52bf525348331e4ee344495c9caf97db3c3f0eb --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--compare.tz].out @@ -0,0 +1,22 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/compare.tz] + +{ parameter (pair mutez mutez) ; + storage (list bool) ; + code { CAR ; + DUP ; + DUP ; + DUP ; + DUP ; + DIP 5 { NIL bool } ; + DIP 4 { DUP ; CAR ; DIP { CDR } ; COMPARE ; LE ; CONS } ; + DIP 3 { DUP ; CAR ; DIP { CDR } ; COMPARE ; GE ; CONS } ; + DIP 2 { DUP ; CAR ; DIP { CDR } ; COMPARE ; LT ; CONS } ; + DIP { DUP ; CAR ; DIP { CDR } ; COMPARE ; GT ; CONS } ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + EQ ; + CONS ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--compare_bytes.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--compare_bytes.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..9913d43599b3b389d6f85fe42a2dccba6722a454 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--compare_bytes.tz].out @@ -0,0 +1,22 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/compare_bytes.tz] + +{ parameter (pair bytes bytes) ; + storage (list bool) ; + code { CAR ; + DUP ; + DUP ; + DUP ; + DUP ; + DIP 5 { NIL bool } ; + DIP 4 { DUP ; CAR ; DIP { CDR } ; COMPARE ; LE ; CONS } ; + DIP 3 { DUP ; CAR ; DIP { CDR } ; COMPARE ; GE ; CONS } ; + DIP 2 { DUP ; CAR ; DIP { CDR } ; COMPARE ; LT ; CONS } ; + DIP { DUP ; CAR ; DIP { CDR } ; COMPARE ; GT ; CONS } ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + EQ ; + CONS ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--fail.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--fail.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..af3e37c7d814f8a0c4b3b103bf2fcb285e18e2df --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--fail.tz].out @@ -0,0 +1,3 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/fail.tz] + +{ parameter unit ; storage unit ; code { { UNIT ; FAILWITH } } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--guestbook.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--guestbook.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..685222a00816845dde2e75027dcbd382b2bfbd6e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--guestbook.tz].out @@ -0,0 +1,18 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/guestbook.tz] + +{ parameter string ; + storage (map address (option string)) ; + code { UNPAIR @message @guestbook ; + SWAP ; + DUP ; + SENDER ; + GET @previous_message ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + { IF_NONE {} { { UNIT ; FAILWITH } } } ; + SWAP ; + SOME ; + SOME ; + SENDER ; + UPDATE ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--macro_annotations.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--macro_annotations.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..39e231f36fe5b009bc813d775831184be478c0b6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--macro_annotations.tz].out @@ -0,0 +1,13 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/macro_annotations.tz] + +{ parameter unit ; + storage (pair (unit %truc) unit) ; + code { DROP ; + UNIT ; + UNIT ; + PAIR %truc ; + UNIT ; + DUP @new_storage 2 ; + DIP { DROP ; DROP } ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--map_caddaadr.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--map_caddaadr.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..98f316d686eed34fa5f76364dc60b02db8d9ff70 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--map_caddaadr.tz].out @@ -0,0 +1,40 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/map_caddaadr.tz] + +{ parameter unit ; + storage (pair (pair nat (pair nat (pair (pair (pair (nat %p) (mutez %value)) nat) nat))) nat) ; + code { { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + CDR @value ; + { PUSH mutez 1000000 ; ADD } ; + SWAP ; + CAR @%% ; + PAIR %@ %value } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ @new_storage } ; + NIL operation ; + SWAP ; + { CDR @%% ; SWAP ; PAIR % %@ } } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--max_in_list.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--max_in_list.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..d1eb7cb00c03e350fa9e3472df0c5cb8774e6a22 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--max_in_list.tz].out @@ -0,0 +1,17 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/max_in_list.tz] + +{ parameter (list int) ; + storage (option int) ; + code { CAR ; + DIP { NONE int } ; + ITER { SWAP ; + IF_NONE + { SOME } + { DIP { DUP } ; + DUP ; + DIP { SWAP } ; + { COMPARE ; LE } ; + IF { DROP } { DIP { DROP } } ; + SOME } } ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--min.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--min.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..35cfbc3e3be57f402a996f6709f20757965a4df7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--min.tz].out @@ -0,0 +1,13 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/min.tz] + +{ parameter (pair int int) ; + storage int ; + code { CAR ; + DUP ; + DUP ; + CAR ; + DIP { CDR } ; + { COMPARE ; LT } ; + IF { CAR } { CDR } ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--pair_macro.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--pair_macro.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..529c89f56a09acc5505400cc21e53ebe250ec771 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--pair_macro.tz].out @@ -0,0 +1,18 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/pair_macro.tz] + +{ parameter unit ; + storage unit ; + code { UNIT ; + UNIT ; + UNIT ; + UNIT ; + UNIT ; + { DIP 3 { PAIR %x4 %x5 } ; + DIP 2 { PAIR %x3 } ; + DIP { PAIR %x2 } ; + PAIR %x1 @name } ; + { CDR ; CDR ; CDR ; CAR %x4 @fourth } ; + DROP ; + CDR ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--set_caddaadr.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--set_caddaadr.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..1a155c49bec748c2299eda2e98815bddcc9a2148 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--set_caddaadr.tz].out @@ -0,0 +1,33 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/set_caddaadr.tz] + +{ parameter mutez ; + storage (pair (pair nat (pair nat (pair (pair (pair (nat %p) (mutez %value)) nat) nat))) nat) ; + code { DUP ; + CAR ; + SWAP ; + CDR ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + DIP { CAR @%% ; { DUP ; CDR %value ; DROP ; CAR @%% ; PAIR %@ %value } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ @toplevel_pair_name } ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--take_my_money.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--take_my_money.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..0fe611b9fed73aa0fc1a4dc97b117650e85be0e8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--take_my_money.tz].out @@ -0,0 +1,14 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/take_my_money.tz] + +{ parameter key_hash ; + storage unit ; + code { CAR ; + IMPLICIT_ACCOUNT ; + DIP { UNIT } ; + PUSH mutez 1000000 ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--unpair_macro.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--unpair_macro.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..8a0d3e670df147d0c2277804f62c12634f001642 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_macros.TestMacroExpansion::test_macro_expansion[macros--unpair_macro.tz].out @@ -0,0 +1,20 @@ +tests_009/test_contract_macros.py::TestMacroExpansion::test_macro_expansion[macros/unpair_macro.tz] + +{ parameter (unit :param_unit) ; + storage (unit :u1) ; + code { DROP ; + UNIT :u4 @a4 ; + UNIT :u3 @a3 ; + UNIT :u2 @a2 ; + UNIT :u1 @a1 ; + PAIR ; + UNPAIR @x1 @x2 ; + { DIP 2 { PAIR %x3 %x4 } ; PAIR %x1 %x2 ; PAIR @p1 } ; + { UNPAIR ; UNPAIR ; DIP 2 { UNPAIR } } ; + { DIP 2 { PAIR %x3 %x4 } ; DIP { PAIR %x2 } ; PAIR %x1 @p2 } ; + { UNPAIR ; DIP { UNPAIR } ; DIP 2 { UNPAIR } } ; + { DIP { PAIR %x2 %x3 } ; DIP { PAIR % %x4 } ; PAIR %x1 @p3 } ; + { UNPAIR ; DIP { UNPAIR } ; DIP { UNPAIR } } ; + DIP { DROP ; DROP ; DROP } ; + NIL operation ; + PAIR } } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_origination_diff.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_origination_diff.out new file mode 100644 index 0000000000000000000000000000000000000000..31516c8fe224459836297bceea8a29808e130094 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_origination_diff.out @@ -0,0 +1,29 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractBigMapOrigination::test_big_map_origination_diff + +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1040000 + Storage limit: 60000 bytes + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter (big_map int int) ; + storage (big_map int int) ; + code { CAR ; NIL operation ; PAIR } } + Initial storage: (Pair 0 { Elt 1 (Some 4) }) + No delegate for this contract + This operation FAILED. + +Ill typed data: 1: (Pair 0 { Elt 1 (Some 4) }) +is not an expression of type big_map int int +At line 1 characters 0 to 26, value (Pair 0 { Elt 1 (Some 4) }) +is invalid for type big_map int int. +At line 1 characters 6 to 7, +Unexpected forged value. +Fatal error: + origination simulation failed diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_origination_id.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_origination_id.out new file mode 100644 index 0000000000000000000000000000000000000000..c3d38f07a3484bc55f608002065f580fb7792a3b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_origination_id.out @@ -0,0 +1,27 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractBigMapOrigination::test_big_map_origination_id + +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1040000 + Storage limit: 60000 bytes + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter (big_map int int) ; + storage (big_map int int) ; + code { CAR ; NIL operation ; PAIR } } + Initial storage: 0 + No delegate for this contract + This operation FAILED. + +Ill typed data: 1: 0 is not an expression of type big_map int int +At line 1 characters 0 to 1, value 0 is invalid for type big_map int int. +At line 1 characters 0 to 1, +Unexpected forged value. +Fatal error: + origination simulation failed diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_origination_literal.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_origination_literal.out new file mode 100644 index 0000000000000000000000000000000000000000..73282f7a6aa024aa00d9a67f0a63133ad18e5410 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_origination_literal.out @@ -0,0 +1,48 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractBigMapOrigination::test_big_map_origination_literal + +Node is bootstrapped. +Estimated gas: 1899.428 units (will add 100 for safety) +Estimated storage: 403 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000486 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 2000 + Storage limit: 423 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000486 + fees(the baker who will include this operation,0) ... +ꜩ0.000486 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter (big_map int int) ; + storage (big_map int int) ; + code { CAR ; NIL operation ; PAIR } } + Initial storage: { Elt 0 0 } + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 146 bytes + Updated big_maps: + New map(0) of type (big_map int int) + Set map(0)[0] to 0 + Paid storage size diff: 146 bytes + Consumed gas: 1899.428 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0365 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as originate_big_map_literal. +Injected block [BLOCK_HASH] diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_transfer_diff.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_transfer_diff.out new file mode 100644 index 0000000000000000000000000000000000000000..f691ed0e13f93713d5aba099d04aa7482a02c787 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_transfer_diff.out @@ -0,0 +1,23 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractBigMapOrigination::test_big_map_transfer_diff + +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0 { Elt 1 (Some 4) }) + This operation FAILED. + +Invalid argument passed to contract [CONTRACT_HASH]. +At (unshown) location 0, value (Pair 0 { Elt 1 (Some 4) }) +is invalid for type big_map int int. +At (unshown) location 1, Unexpected forged value. +Fatal error: + transfer simulation failed diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_transfer_id.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_transfer_id.out new file mode 100644 index 0000000000000000000000000000000000000000..a3fd6ef13bbe5af2a7f6ed79d0f66baaa3a569ec --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractBigMapOrigination::test_big_map_transfer_id.out @@ -0,0 +1,22 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractBigMapOrigination::test_big_map_transfer_id + +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: 0 + This operation FAILED. + +Invalid argument passed to contract [CONTRACT_HASH]. +At (unshown) location 0, value 0 is invalid for type big_map int int. +At (unshown) location 0, Unexpected forged value. +Fatal error: + transfer simulation failed diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainLevel::test_level.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainLevel::test_level.out new file mode 100644 index 0000000000000000000000000000000000000000..a966c5b17006ae625bfd491008d8aa2f2468f22a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainLevel::test_level.out @@ -0,0 +1,121 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainLevel::test_level + +Node is bootstrapped. +Estimated gas: 1578.332 units (will add 100 for safety) +Estimated storage: 300 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1679 + Storage limit: 320 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000441 + fees(the baker who will include this operation,0) ... +ꜩ0.000441 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ100 + Script: + { parameter unit ; + storage nat ; + code { DROP ; LEVEL ; NIL operation ; PAIR } } + Initial storage: 9999999 + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 43 bytes + Paid storage size diff: 43 bytes + Consumed gas: 1578.332 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.01075 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + +New contract [CONTRACT_HASH] originated. +Contract memorized as level. +Injected block [BLOCK_HASH] +Injected block [BLOCK_HASH] +Node is bootstrapped. +Estimated gas: 2226.375 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000485 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 2327 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000485 + fees(the baker who will include this operation,0) ... +ꜩ0.000485 + Transaction: + Amount: ꜩ500 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 4 + Storage size: 40 bytes + Consumed gas: 2226.375 + Balance updates: + [CONTRACT_HASH] ... -ꜩ500 + [CONTRACT_HASH] ... +ꜩ500 + +Injected block [BLOCK_HASH] +{ "level": [LEVEL], "proto": 1, + "predecessor": "[BLOCK_HASH]", + "timestamp": "[TIMESTAMP]", "validation_pass": 4, + "operations_hash": "[OPERATION_HASH]", + "fitness": "[FITNESS]", + "context": "[CONTEXT]" } +4 +Injected block [BLOCK_HASH] +Injected block [BLOCK_HASH] +4 +Node is bootstrapped. +Estimated gas: 2226.369 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000485 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 2327 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000485 + fees(the baker who will include this operation,0) ... +ꜩ0.000485 + Transaction: + Amount: ꜩ500 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 7 + Storage size: 40 bytes + Consumed gas: 2226.369 + Balance updates: + [CONTRACT_HASH] ... -ꜩ500 + [CONTRACT_HASH] ... +ꜩ500 + +Injected block [BLOCK_HASH] +7 diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_contract_fails.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_contract_fails.out new file mode 100644 index 0000000000000000000000000000000000000000..c72046cbbde50bb84a02d0db62d0c2c98c9e1779 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_contract_fails.out @@ -0,0 +1,2 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_contract_fails + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_gen_keys.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_gen_keys.out new file mode 100644 index 0000000000000000000000000000000000000000..fc7cc444202d945b033015e86d46ebaef8d58a16 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_gen_keys.out @@ -0,0 +1,2 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_gen_keys + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_init_proxy.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_init_proxy.out new file mode 100644 index 0000000000000000000000000000000000000000..5237fb877279d7ff0449e0ad2856c76763b9ec95 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_init_proxy.out @@ -0,0 +1,51 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_init_proxy + +Node is bootstrapped. +Estimated gas: 1665.810 units (will add 100 for safety) +Estimated storage: 312 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000463 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1766 + Storage limit: 332 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000463 + fees(the baker who will include this operation,2) ... +ꜩ0.000463 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter (contract unit) ; + storage unit ; + code { UNPAIR ; + AMOUNT ; + UNIT ; + TRANSFER_TOKENS ; + DIP { NIL operation } ; + CONS ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 55 bytes + Paid storage size diff: 55 bytes + Consumed gas: 1665.810 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.01375 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as proxy. +Injected block [BLOCK_HASH] diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_now.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_now.out new file mode 100644 index 0000000000000000000000000000000000000000..1d0a81cce5571f29f03221c5ad74dfe3846082ce --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_now.out @@ -0,0 +1,2 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_now + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_self.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_self.out new file mode 100644 index 0000000000000000000000000000000000000000..61502d3dc3f83f0f4aaf66ccbcf371ba1e05d085 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_self.out @@ -0,0 +1,2 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_self + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_sender.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_sender.out new file mode 100644 index 0000000000000000000000000000000000000000..8e31985a113f0c2efd8bf6f45b1d75c7b94b8fb6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_sender.out @@ -0,0 +1,2 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_sender + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_set_delegate.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_set_delegate.out new file mode 100644 index 0000000000000000000000000000000000000000..8a5df1a858d6faf0469779eda3bfcf915f9885cd --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_set_delegate.out @@ -0,0 +1,121 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_set_delegate + +Node is bootstrapped. +Estimated gas: 1636.164 units (will add 100 for safety) +Estimated storage: 308 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000456 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1737 + Storage limit: 328 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000456 + fees(the baker who will include this operation,4) ... +ꜩ0.000456 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter (option key_hash) ; + storage unit ; + code { UNPAIR ; SET_DELEGATE ; DIP { NIL operation } ; CONS ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 51 bytes + Paid storage size diff: 51 bytes + Consumed gas: 1636.164 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.01275 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as set_delegate. +Injected block [BLOCK_HASH] +Injected block [BLOCK_HASH] +none +Node is bootstrapped. +Estimated gas: 3519.936 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000658 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 3620 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000658 + fees(the baker who will include this operation,4) ... +ꜩ0.000658 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Some "[CONTRACT_HASH]") + This transaction was successfully applied + Updated storage: Unit + Storage size: 51 bytes + Consumed gas: 2519.936 + Internal operations: + Delegation: + Contract: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This delegation was successfully applied + Consumed gas: 1000 + +Injected block [BLOCK_HASH] +[CONTRACT_HASH] (known as bootstrap5) +Node is bootstrapped. +Estimated gas: 3494.396 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000615 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 3595 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000615 + fees(the baker who will include this operation,4) ... +ꜩ0.000615 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: None + This transaction was successfully applied + Updated storage: Unit + Storage size: 51 bytes + Consumed gas: 2494.396 + Internal operations: + Delegation: + Contract: [CONTRACT_HASH] + To: nobody + This delegation was successfully applied + Consumed gas: 1000 + +Injected block [BLOCK_HASH] +none diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice.out new file mode 100644 index 0000000000000000000000000000000000000000..3bbbb1cdbfcb59ab56dba1b3a36dcd8a71c512bc --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice.out @@ -0,0 +1,85 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_slice + +Node is bootstrapped. +Estimated gas: 4015.117 units (will add 100 for safety) +Estimated storage: 835 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.001242 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 4116 + Storage limit: 855 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.001242 + fees(the baker who will include this operation,3) ... +ꜩ0.001242 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter (pair bytes signature) ; + storage key ; + code { DUP ; + CAAR ; + DUP ; + SIZE ; + PUSH nat 128 ; + SWAP ; + SUB ; + ISNAT ; + ASSERT_SOME ; + PUSH nat 128 ; + SLICE @payload ; + ASSERT_SOME ; + DUP ; + DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + SHA256 ; + ASSERT_CMPEQ } ; + DUP ; + DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + BLAKE2B ; + ASSERT_CMPEQ } ; + DUP ; + DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + SHA512 ; + ASSERT_CMPEQ } ; + DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + SWAP ; + DIP { SWAP } ; + CHECK_SIGNATURE ; + ASSERT ; + CDR ; + DUP ; + HASH_KEY ; + IMPLICIT_ACCOUNT ; + BALANCE ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } } + Initial storage: + "[OPERATION_HASH]na" + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 578 bytes + Paid storage size diff: 578 bytes + Consumed gas: 4015.117 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.1445 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as slices. +Injected block [BLOCK_HASH] diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0 \"spsig1PPUFZucuAQybs5wsqs.818025e860.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0 \"spsig1PPUFZucuAQybs5wsqs.818025e860.out" new file mode 100644 index 0000000000000000000000000000000000000000..2d13be9c8c97c7bb21ff873748fd330b6eb0a7dc --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0 \"spsig1PPUFZucuAQybs5wsqs.818025e860.out" @@ -0,0 +1,66 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")] + +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0xe009ab79e8b84ef0 + "sp[SIGNATURE]m") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 11 characters 9 to 20, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75.2d6806d54e.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75.2d6806d54e.out new file mode 100644 index 0000000000000000000000000000000000000000..d00239846ca4e8e21a62bc4189c679c3a7a795a6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75.2d6806d54e.out @@ -0,0 +1,66 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2deaad01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")] + +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair [OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH]000085341554349535345 + "sp[SIGNATURE]m") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 22 characters 15 to 27, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75.378d03ae2d.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75.378d03ae2d.out new file mode 100644 index 0000000000000000000000000000000000000000..5e64341ef62c1453bc1e8cd58845ef98dde3a65a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75.378d03ae2d.out @@ -0,0 +1,66 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150733eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")] + +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair [OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH]000085341554349535345 + "sp[SIGNATURE]m") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 26 characters 15 to 27, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75.57fdc7ad1c.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75.57fdc7ad1c.out new file mode 100644 index 0000000000000000000000000000000000000000..6ab96ee738d058dac7cffa4398bb54b9431dfbf5 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75.57fdc7ad1c.out @@ -0,0 +1,66 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_slice_fails[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "p2sigsceCzcDw2AeYDzUonj4JT341WC9Px4wdhHBxbZcG1FhfqFVuG7f2fGCzrEHSAZgrsrQWpxduDPk9qZRgrpzwJnSHC3gZJ")] + +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair [OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH]000085341554349535345 + "p2[SIGNATURE]") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 31 characters 9 to 15, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xeaa9ab79e8b84ef0e55c43a9a857214d8761e67b75.c583c796bf.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xeaa9ab79e8b84ef0e55c43a9a857214d8761e67b75.c583c796bf.out new file mode 100644 index 0000000000000000000000000000000000000000..24dc92644d9b1f11d09efc694e76f999528039ee --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_fails[(Pair 0xeaa9ab79e8b84ef0e55c43a9a857214d8761e67b75.c583c796bf.out @@ -0,0 +1,66 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_slice_fails[(Pair 0xeaa9ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")] + +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair [OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH]000085341554349535345 + "sp[SIGNATURE]m") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 18 characters 15 to 27, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_success[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b.7da5c9014e.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_success[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b.7da5c9014e.out new file mode 100644 index 0000000000000000000000000000000000000000..093b595fd01132fe5734274e8b8746d5afa77664 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_slice_success[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b.7da5c9014e.out @@ -0,0 +1,45 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_slice_success[(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")] + +Node is bootstrapped. +Estimated gas: 6724.306 units (will add 100 for safety) +Estimated storage: 257 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.00119 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 6825 + Storage limit: 277 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.00119 + fees(the baker who will include this operation,3) ... +ꜩ0.00119 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair [OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH][OPERATION_HASH]000085341554349535345 + "sp[SIGNATURE]m") + This transaction was successfully applied + Updated storage: + [OPERATION_HASH]48f709699019725ba + Storage size: 578 bytes + Consumed gas: 5297.306 + Internal operations: + Transaction: + Amount: ꜩ1000 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Consumed gas: 1427 + Balance updates: + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + [CONTRACT_HASH] ... -ꜩ0.06425 + +Injected block [BLOCK_HASH] diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_source.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_source.out new file mode 100644 index 0000000000000000000000000000000000000000..289f3260197b5220f0168f39f7464b1776bac6f0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_source.out @@ -0,0 +1,117 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_source + +Node is bootstrapped. +Estimated gas: 1662.020 units (will add 100 for safety) +Estimated storage: 322 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000487 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1763 + Storage limit: 342 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000487 + fees(the baker who will include this operation,2) ... +ꜩ0.000487 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter unit ; + storage address ; + code { DROP ; SOURCE ; NIL operation ; PAIR } } + Initial storage: "[CONTRACT_HASH]" + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 65 bytes + Paid storage size diff: 65 bytes + Consumed gas: 1662.020 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.01625 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as source. +Injected block [BLOCK_HASH] +Node is bootstrapped. +Estimated gas: 2543.074 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000513 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 2644 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000513 + fees(the baker who will include this operation,2) ... +ꜩ0.000513 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c + Storage size: 65 bytes + Consumed gas: 2543.074 + +Injected block [BLOCK_HASH] +"[CONTRACT_HASH]" +[CONTRACT_HASH] + +Node is bootstrapped. +Estimated gas: 5960.632 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000901 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 6061 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000901 + fees(the baker who will include this operation,2) ... +ꜩ0.000901 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 55 bytes + Consumed gas: 3417.558 + Internal operations: + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c + Storage size: 65 bytes + Consumed gas: 2543.074 + +Injected block [BLOCK_HASH] +"[CONTRACT_HASH]" diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_split_bytes.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_split_bytes.out new file mode 100644 index 0000000000000000000000000000000000000000..2adb751e116aa87ed7ada1d0ae8087cc251d85bf --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_split_bytes.out @@ -0,0 +1,135 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_split_bytes + +Node is bootstrapped. +Estimated gas: 2578.581 units (will add 100 for safety) +Estimated storage: 511 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000753 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 2679 + Storage limit: 531 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000753 + fees(the baker who will include this operation,3) ... +ꜩ0.000753 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter bytes ; + storage (list bytes) ; + code { UNPAIR ; + DIP { NIL bytes ; SWAP ; ITER { CONS } } ; + DUP ; + SIZE ; + PUSH nat 0 ; + CMPNEQ ; + DIP { PUSH @index nat 0 } ; + LOOP { PAIR ; + DUP ; + DIP { UNPAIR ; DIP { PUSH nat 1 } ; SLICE ; ASSERT_SOME ; CONS @storage } ; + UNPAIR ; + PUSH nat 1 ; + ADD @index ; + DUP ; + DIP { DIP { DUP } ; SWAP ; SIZE ; CMPNEQ } ; + SWAP } ; + DROP ; + DROP ; + NIL bytes ; + SWAP ; + ITER { CONS } ; + NIL operation ; + PAIR } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 254 bytes + Paid storage size diff: 254 bytes + Consumed gas: 2578.581 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0635 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as split_bytes. +Injected block [BLOCK_HASH] +Node is bootstrapped. +Estimated gas: 3486.397 units (will add 100 for safety) +Estimated storage: 18 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.00062 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 3587 + Storage limit: 38 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.00062 + fees(the baker who will include this operation,4) ... +ꜩ0.00062 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: 0xaabbcc + This transaction was successfully applied + Updated storage: { 0xaa ; 0xbb ; 0xcc } + Storage size: 272 bytes + Paid storage size diff: 18 bytes + Consumed gas: 3486.397 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0045 + +Injected block [BLOCK_HASH] +{ 0xaa ; 0xbb ; 0xcc } +Node is bootstrapped. +Estimated gas: 3626.737 units (will add 100 for safety) +Estimated storage: 18 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000634 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 3727 + Storage limit: 38 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000634 + fees(the baker who will include this operation,4) ... +ꜩ0.000634 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: 0xddeeff + This transaction was successfully applied + Updated storage: { 0xaa ; 0xbb ; 0xcc ; 0xdd ; 0xee ; 0xff } + Storage size: 290 bytes + Paid storage size diff: 18 bytes + Consumed gas: 3626.737 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0045 + +Injected block [BLOCK_HASH] +{ 0xaa ; 0xbb ; 0xcc ; 0xdd ; 0xee ; 0xff } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_split_string.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_split_string.out new file mode 100644 index 0000000000000000000000000000000000000000..f343381caccac514d9693e93849954090d1f250a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_split_string.out @@ -0,0 +1,135 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_split_string + +Node is bootstrapped. +Estimated gas: 2578.581 units (will add 100 for safety) +Estimated storage: 511 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000753 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 2679 + Storage limit: 531 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000753 + fees(the baker who will include this operation,3) ... +ꜩ0.000753 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter string ; + storage (list string) ; + code { UNPAIR ; + DIP { NIL string ; SWAP ; ITER { CONS } } ; + DUP ; + SIZE ; + PUSH nat 0 ; + CMPNEQ ; + DIP { PUSH @index nat 0 } ; + LOOP { PAIR ; + DUP ; + DIP { UNPAIR ; DIP { PUSH nat 1 } ; SLICE ; ASSERT_SOME ; CONS @storage } ; + UNPAIR ; + PUSH nat 1 ; + ADD @index ; + DUP ; + DIP { DIP { DUP } ; SWAP ; SIZE ; CMPNEQ } ; + SWAP } ; + DROP ; + DROP ; + NIL string ; + SWAP ; + ITER { CONS } ; + NIL operation ; + PAIR } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 254 bytes + Paid storage size diff: 254 bytes + Consumed gas: 2578.581 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0635 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as split_string. +Injected block [BLOCK_HASH] +Node is bootstrapped. +Estimated gas: 3456.441 units (will add 100 for safety) +Estimated storage: 18 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000617 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 3557 + Storage limit: 38 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000617 + fees(the baker who will include this operation,3) ... +ꜩ0.000617 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: "abc" + This transaction was successfully applied + Updated storage: { "a" ; "b" ; "c" } + Storage size: 272 bytes + Paid storage size diff: 18 bytes + Consumed gas: 3456.441 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0045 + +Injected block [BLOCK_HASH] +{ "a" ; "b" ; "c" } +Node is bootstrapped. +Estimated gas: 3512.853 units (will add 100 for safety) +Estimated storage: 18 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000623 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 3613 + Storage limit: 38 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000623 + fees(the baker who will include this operation,3) ... +ꜩ0.000623 + Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: "def" + This transaction was successfully applied + Updated storage: { "a" ; "b" ; "c" ; "d" ; "e" ; "f" } + Storage size: 290 bytes + Paid storage size diff: 18 bytes + Consumed gas: 3512.853 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0045 + +Injected block [BLOCK_HASH] +{ "a" ; "b" ; "c" ; "d" ; "e" ; "f" } diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_store_input.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_store_input.out new file mode 100644 index 0000000000000000000000000000000000000000..53a211b143b0965389f031889bc9b0fdcf081c51 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_store_input.out @@ -0,0 +1,180 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_store_input + +Node is bootstrapped. +Estimated gas: 1427 units (will add 100 for safety) +Estimated storage: 257 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000406 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1527 + Storage limit: 277 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000406 + fees(the baker who will include this operation,0) ... +ꜩ0.000406 + Transaction: + Amount: ꜩ1000 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Consumed gas: 1427 + Balance updates: + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + [CONTRACT_HASH] ... -ꜩ0.06425 + +Injected block [BLOCK_HASH] +Node is bootstrapped. +Estimated gas: 1427 units (will add 100 for safety) +Estimated storage: 257 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000406 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1527 + Storage limit: 277 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000406 + fees(the baker who will include this operation,0) ... +ꜩ0.000406 + Transaction: + Amount: ꜩ2000 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Consumed gas: 1427 + Balance updates: + [CONTRACT_HASH] ... -ꜩ2000 + [CONTRACT_HASH] ... +ꜩ2000 + [CONTRACT_HASH] ... -ꜩ0.06425 + +Injected block [BLOCK_HASH] +1000 ꜩ +2000 ꜩ +Node is bootstrapped. +Estimated gas: 1561.588 units (will add 100 for safety) +Estimated storage: 298 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000438 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1662 + Storage limit: 318 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000438 + fees(the baker who will include this operation,0) ... +ꜩ0.000438 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ100 + Script: + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } + Initial storage: "" + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 41 bytes + Paid storage size diff: 41 bytes + Consumed gas: 1561.588 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.01025 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + +New contract [CONTRACT_HASH] originated. +Contract memorized as store_input. +Injected block [BLOCK_HASH] +Node is bootstrapped. +Estimated gas: 2211.644 units (will add 100 for safety) +Estimated storage: 7 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.0005 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 2312 + Storage limit: 27 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.0005 + fees(the baker who will include this operation,0) ... +ꜩ0.0005 + Transaction: + Amount: ꜩ100 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: "abcdefg" + This transaction was successfully applied + Updated storage: "abcdefg" + Storage size: 48 bytes + Paid storage size diff: 7 bytes + Consumed gas: 2211.644 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.00175 + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + +Injected block [BLOCK_HASH] +200 ꜩ +"abcdefg" +Node is bootstrapped. +Estimated gas: 2211.672 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000496 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 2312 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000496 + fees(the baker who will include this operation,0) ... +ꜩ0.000496 + Transaction: + Amount: ꜩ100 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: "xyz" + This transaction was successfully applied + Updated storage: "xyz" + Storage size: 44 bytes + Consumed gas: 2211.672 + Balance updates: + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + +Injected block [BLOCK_HASH] +"xyz" diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_trace_origination[compare_big_type.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_trace_origination[compare_big_type.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..ceceb1385948995b29fc47148b67a0405ec60052 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_trace_origination[compare_big_type.tz].out @@ -0,0 +1,91 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_trace_origination[compare_big_type.tz] + +Node is bootstrapped. +Estimated gas: 4583.242 units (will add 100 for safety) +Estimated storage: 385 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000828 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 4684 + Storage limit: 405 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000828 + fees(the baker who will include this operation,4) ... +ꜩ0.000828 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter unit ; + storage unit ; + code { DROP ; + PUSH nat 0 ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DROP ; + UNIT ; + NIL operation ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 128 bytes + Paid storage size diff: 128 bytes + Consumed gas: 4583.242 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.032 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as compare_big_type. +Injected block [BLOCK_HASH] +Injected block [BLOCK_HASH] diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_trace_origination[compare_big_type2.tz].out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_trace_origination[compare_big_type2.tz].out new file mode 100644 index 0000000000000000000000000000000000000000..352c2149f02495102b44db8fce98ceb6724c1536 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_trace_origination[compare_big_type2.tz].out @@ -0,0 +1,95 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_trace_origination[compare_big_type2.tz] + +Node is bootstrapped. +Estimated gas: 5015.304 units (will add 100 for safety) +Estimated storage: 393 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000879 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 5116 + Storage limit: 413 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000879 + fees(the baker who will include this operation,5) ... +ꜩ0.000879 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter unit ; + storage unit ; + code { DROP ; + PUSH nat 0 ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DROP ; + UNIT ; + NIL operation ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 136 bytes + Paid storage size diff: 136 bytes + Consumed gas: 5015.304 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.034 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as compare_big_type2. +Injected block [BLOCK_HASH] +Injected block [BLOCK_HASH] diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_transfer_amount.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_transfer_amount.out new file mode 100644 index 0000000000000000000000000000000000000000..71a55cce7be1e4af977390d43723cdc4b05819bd --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_transfer_amount.out @@ -0,0 +1,80 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_transfer_amount + +Node is bootstrapped. +Estimated gas: 1576.320 units (will add 100 for safety) +Estimated storage: 297 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000438 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1677 + Storage limit: 317 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000438 + fees(the baker who will include this operation,0) ... +ꜩ0.000438 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ100 + Script: + { parameter unit ; + storage mutez ; + code { DROP ; AMOUNT ; NIL operation ; PAIR } } + Initial storage: 0 + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 40 bytes + Paid storage size diff: 40 bytes + Consumed gas: 1576.320 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.01 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + +New contract [CONTRACT_HASH] originated. +Contract memorized as transfer_amount. +Injected block [BLOCK_HASH] +Node is bootstrapped. +Estimated gas: 2224.340 units (will add 100 for safety) +Estimated storage: 4 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000485 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 2325 + Storage limit: 24 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000485 + fees(the baker who will include this operation,0) ... +ꜩ0.000485 + Transaction: + Amount: ꜩ500 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 500000000 + Storage size: 44 bytes + Paid storage size diff: 4 bytes + Consumed gas: 2224.340 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.001 + [CONTRACT_HASH] ... -ꜩ500 + [CONTRACT_HASH] ... +ꜩ500 + +Injected block [BLOCK_HASH] +500000000 diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_transfer_tokens.out b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_transfer_tokens.out new file mode 100644 index 0000000000000000000000000000000000000000..5b70ef298a7538b197f5d6b046a62cee326b90f6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_onchain_opcodes.TestContractOnchainOpcodes::test_transfer_tokens.out @@ -0,0 +1,232 @@ +tests_009/test_contract_onchain_opcodes.py::TestContractOnchainOpcodes::test_transfer_tokens + +Node is bootstrapped. +Estimated gas: 1563.562 units (will add 100 for safety) +Estimated storage: 295 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000435 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1664 + Storage limit: 315 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000435 + fees(the baker who will include this operation,1) ... +ꜩ0.000435 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ100 + Script: + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 38 bytes + Paid storage size diff: 38 bytes + Consumed gas: 1563.562 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0095 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + +New contract [CONTRACT_HASH] originated. +Contract memorized as test_transfer_account1. +Injected block [BLOCK_HASH] +Node is bootstrapped. +Estimated gas: 1563.562 units (will add 100 for safety) +Estimated storage: 295 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000435 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1664 + Storage limit: 315 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000435 + fees(the baker who will include this operation,1) ... +ꜩ0.000435 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ20 + Script: + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 38 bytes + Paid storage size diff: 38 bytes + Consumed gas: 1563.562 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0095 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ20 + [CONTRACT_HASH] ... +ꜩ20 + +New contract [CONTRACT_HASH] originated. +Contract memorized as test_transfer_account2. +Injected block [BLOCK_HASH] +Node is bootstrapped. +Estimated gas: 1723.764 units (will add 100 for safety) +Estimated storage: 323 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.00048 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 1824 + Storage limit: 343 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.00048 + fees(the baker who will include this operation,1) ... +ꜩ0.00048 + Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1000 + Script: + { parameter (contract unit) ; + storage unit ; + code { CAR ; + DIP { UNIT } ; + PUSH mutez 100000000 ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 66 bytes + Paid storage size diff: 66 bytes + Consumed gas: 1723.764 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.0165 + [CONTRACT_HASH] ... -ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as transfer_tokens. +Injected block [BLOCK_HASH] +100 ꜩ +[CONTRACT_HASH] + +Node is bootstrapped. +Estimated gas: 5463.131 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000854 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 5564 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000854 + fees(the baker who will include this operation,1) ... +ꜩ0.000854 + Transaction: + Amount: ꜩ100 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 66 bytes + Consumed gas: 3251.631 + Balance updates: + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + Internal operations: + Transaction: + Amount: ꜩ100 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: Unit + Storage size: 38 bytes + Consumed gas: 2211.500 + Balance updates: + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + +Injected block [BLOCK_HASH] +200 ꜩ +[CONTRACT_HASH] + +Node is bootstrapped. +Estimated gas: 5463.131 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[BLOCK_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [BLOCK_HASH] to be included --confirmations 30 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [CONTRACT_HASH] + Fee to the baker: ꜩ0.000854 + Expected counter: [EXPECTED_COUNTER] + Gas limit: 5564 + Storage limit: 0 bytes + Balance updates: + [CONTRACT_HASH] ................ -ꜩ0.000854 + fees(the baker who will include this operation,1) ... +ꜩ0.000854 + Transaction: + Amount: ꜩ100 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 66 bytes + Consumed gas: 3251.631 + Balance updates: + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + Internal operations: + Transaction: + Amount: ꜩ100 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: Unit + Storage size: 38 bytes + Consumed gas: 2211.500 + Balance updates: + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + +Injected block [BLOCK_HASH] +120 ꜩ diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 4) {})-\"hello\"-(Pa.ed8a8c90dc.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 4) {})-\"hello\"-(Pa.ed8a8c90dc.out" new file mode 100644 index 0000000000000000000000000000000000000000..4ab2091c36a74f5a39d51bb4b11c8359da93f274 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 4) {})-\"hello\"-(Pa.ed8a8c90dc.out" @@ -0,0 +1,42 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 4) {})-"hello"-(Pair None 0)-big_map_diff10] + +storage + (Pair None 0) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["hello"] to 4 +trace + - location: 11 (remaining gas: 1039988.651 units remaining) + [ (Pair "hello" (Some 4) {}) ] + - location: 13 (remaining gas: 1039988.541 units remaining) + [ "hello" @parameter + (Pair (Some 4) {}) @storage ] + - location: 16 (remaining gas: 1039988.386 units remaining) + [ (Some 4) + {} ] + - location: 15 (remaining gas: 1039988.341 units remaining) + [ (Some 4) + {} ] + - location: 14 (remaining gas: 1039988.341 units remaining) + [ "hello" @parameter + (Some 4) + {} ] + - location: -1 (remaining gas: 1039988.296 units remaining) + [ "hello" @parameter + (Some 4) + {} ] + - location: 17 (remaining gas: 1039975.349 units remaining) + [ None + { Elt "hello" 4 } ] + - location: 18 (remaining gas: 1039975.274 units remaining) + [ (Pair None { Elt "hello" 4 }) ] + - location: 19 (remaining gas: 1039975.199 units remaining) + [ {} + (Pair None { Elt "hello" 4 }) ] + - location: 21 (remaining gas: 1039975.124 units remaining) + [ (Pair {} None { Elt "hello" 4 }) ] + - location: -1 (remaining gas: 1039975.079 units remaining) + [ (Pair {} None { Elt "hello" 4 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 5) { Elt \"hello\" 4.4ba77dda56.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 5) { Elt \"hello\" 4.4ba77dda56.out" new file mode 100644 index 0000000000000000000000000000000000000000..5d8190dea38faeab591adc96440dcb1205457816 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 5) { Elt \"hello\" 4.4ba77dda56.out" @@ -0,0 +1,43 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 5) { Elt "hello" 4 })-"hi"-(Pair None 0)-big_map_diff13] + +storage + (Pair None 0) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["hello"] to 4 + Set map(0)["hi"] to 5 +trace + - location: 11 (remaining gas: 1039975.301 units remaining) + [ (Pair "hi" (Some 5) { Elt "hello" 4 }) ] + - location: 13 (remaining gas: 1039975.191 units remaining) + [ "hi" @parameter + (Pair (Some 5) { Elt "hello" 4 }) @storage ] + - location: 16 (remaining gas: 1039975.036 units remaining) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 15 (remaining gas: 1039974.991 units remaining) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 14 (remaining gas: 1039974.991 units remaining) + [ "hi" @parameter + (Some 5) + { Elt "hello" 4 } ] + - location: -1 (remaining gas: 1039974.946 units remaining) + [ "hi" @parameter + (Some 5) + { Elt "hello" 4 } ] + - location: 17 (remaining gas: 1039965.996 units remaining) + [ None + { Elt "hello" 4 ; Elt "hi" 5 } ] + - location: 18 (remaining gas: 1039965.921 units remaining) + [ (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: 19 (remaining gas: 1039965.846 units remaining) + [ {} + (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: 21 (remaining gas: 1039965.771 units remaining) + [ (Pair {} None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: -1 (remaining gas: 1039965.726 units remaining) + [ (Pair {} None { Elt "hello" 4 ; Elt "hi" 5 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 5) { Elt \"hello\" 4.662e6b84f7.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 5) { Elt \"hello\" 4.662e6b84f7.out" new file mode 100644 index 0000000000000000000000000000000000000000..6aa3b5e68b3c4ee8bcf14e28ea638958b64a3524 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 5) { Elt \"hello\" 4.662e6b84f7.out" @@ -0,0 +1,42 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair (Some 5) { Elt "hello" 4 })-"hello"-(Pair (Some 4) 0)-big_map_diff12] + +storage + (Pair (Some 4) 0) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["hello"] to 5 +trace + - location: 11 (remaining gas: 1039975.271 units remaining) + [ (Pair "hello" (Some 5) { Elt "hello" 4 }) ] + - location: 13 (remaining gas: 1039975.161 units remaining) + [ "hello" @parameter + (Pair (Some 5) { Elt "hello" 4 }) @storage ] + - location: 16 (remaining gas: 1039975.006 units remaining) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 15 (remaining gas: 1039974.961 units remaining) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 14 (remaining gas: 1039974.961 units remaining) + [ "hello" @parameter + (Some 5) + { Elt "hello" 4 } ] + - location: -1 (remaining gas: 1039974.916 units remaining) + [ "hello" @parameter + (Some 5) + { Elt "hello" 4 } ] + - location: 17 (remaining gas: 1039961.963 units remaining) + [ (Some 4) + { Elt "hello" 5 } ] + - location: 18 (remaining gas: 1039961.888 units remaining) + [ (Pair (Some 4) { Elt "hello" 5 }) ] + - location: 19 (remaining gas: 1039961.813 units remaining) + [ {} + (Pair (Some 4) { Elt "hello" 5 }) ] + - location: 21 (remaining gas: 1039961.738 units remaining) + [ (Pair {} (Some 4) { Elt "hello" 5 }) ] + - location: -1 (remaining gas: 1039961.693 units remaining) + [ (Pair {} (Some 4) { Elt "hello" 5 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt \"1\" 1 ; .7806be875b.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt \"1\" 1 ; .7806be875b.out" new file mode 100644 index 0000000000000000000000000000000000000000..68a6315bd7c49111e993815cc3ffa44563b09efd --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt \"1\" 1 ; .7806be875b.out" @@ -0,0 +1,43 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt "1" 1 ; Elt "2" 2 })-"1"-(Pair (Some 1) 0)-big_map_diff15] + +storage + (Pair (Some 1) 0) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["2"] to 2 + Unset map(0)["1"] +trace + - location: 11 (remaining gas: 1039970.137 units remaining) + [ (Pair "1" None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 13 (remaining gas: 1039970.027 units remaining) + [ "1" @parameter + (Pair None { Elt "1" 1 ; Elt "2" 2 }) @storage ] + - location: 16 (remaining gas: 1039969.872 units remaining) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 15 (remaining gas: 1039969.827 units remaining) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 14 (remaining gas: 1039969.827 units remaining) + [ "1" @parameter + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: -1 (remaining gas: 1039969.782 units remaining) + [ "1" @parameter + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 17 (remaining gas: 1039960.830 units remaining) + [ (Some 1) + { Elt "2" 2 } ] + - location: 18 (remaining gas: 1039960.755 units remaining) + [ (Pair (Some 1) { Elt "2" 2 }) ] + - location: 19 (remaining gas: 1039960.680 units remaining) + [ {} + (Pair (Some 1) { Elt "2" 2 }) ] + - location: 21 (remaining gas: 1039960.605 units remaining) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + - location: -1 (remaining gas: 1039960.560 units remaining) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt \"1\" 1 ; .7beec6cc30.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt \"1\" 1 ; .7beec6cc30.out" new file mode 100644 index 0000000000000000000000000000000000000000..b5c192d24643db7d258c4be0c9d9aab4013b7d8a --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt \"1\" 1 ; .7beec6cc30.out" @@ -0,0 +1,43 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt "1" 1 ; Elt "2" 2 })-"1"-(Pair (Some 1) 0)-big_map_diff14] + +storage + (Pair (Some 1) 0) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["2"] to 2 + Unset map(0)["1"] +trace + - location: 11 (remaining gas: 1039970.137 units remaining) + [ (Pair "1" None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 13 (remaining gas: 1039970.027 units remaining) + [ "1" @parameter + (Pair None { Elt "1" 1 ; Elt "2" 2 }) @storage ] + - location: 16 (remaining gas: 1039969.872 units remaining) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 15 (remaining gas: 1039969.827 units remaining) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 14 (remaining gas: 1039969.827 units remaining) + [ "1" @parameter + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: -1 (remaining gas: 1039969.782 units remaining) + [ "1" @parameter + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 17 (remaining gas: 1039960.830 units remaining) + [ (Some 1) + { Elt "2" 2 } ] + - location: 18 (remaining gas: 1039960.755 units remaining) + [ (Pair (Some 1) { Elt "2" 2 }) ] + - location: 19 (remaining gas: 1039960.680 units remaining) + [ {} + (Pair (Some 1) { Elt "2" 2 }) ] + - location: 21 (remaining gas: 1039960.605 units remaining) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + - location: -1 (remaining gas: 1039960.560 units remaining) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt \"hello\" 4 })-.2e17580138.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt \"hello\" 4 })-.2e17580138.out" new file mode 100644 index 0000000000000000000000000000000000000000..dd89e3c9f67b7839a426a09e1d7f96dc34214f22 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt \"hello\" 4 })-.2e17580138.out" @@ -0,0 +1,42 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None { Elt "hello" 4 })-"hello"-(Pair (Some 4) 0)-big_map_diff11] + +storage + (Pair (Some 4) 0) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Unset map(0)["hello"] +trace + - location: 11 (remaining gas: 1039975.511 units remaining) + [ (Pair "hello" None { Elt "hello" 4 }) ] + - location: 13 (remaining gas: 1039975.401 units remaining) + [ "hello" @parameter + (Pair None { Elt "hello" 4 }) @storage ] + - location: 16 (remaining gas: 1039975.246 units remaining) + [ None + { Elt "hello" 4 } ] + - location: 15 (remaining gas: 1039975.201 units remaining) + [ None + { Elt "hello" 4 } ] + - location: 14 (remaining gas: 1039975.201 units remaining) + [ "hello" @parameter + None + { Elt "hello" 4 } ] + - location: -1 (remaining gas: 1039975.156 units remaining) + [ "hello" @parameter + None + { Elt "hello" 4 } ] + - location: 17 (remaining gas: 1039962.203 units remaining) + [ (Some 4) + {} ] + - location: 18 (remaining gas: 1039962.128 units remaining) + [ (Pair (Some 4) {}) ] + - location: 19 (remaining gas: 1039962.053 units remaining) + [ {} + (Pair (Some 4) {}) ] + - location: 21 (remaining gas: 1039961.978 units remaining) + [ (Pair {} (Some 4) {}) ] + - location: -1 (remaining gas: 1039961.933 units remaining) + [ (Pair {} (Some 4) {}) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None {})-\"hello\"-(Pair N.ae2570aa95.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None {})-\"hello\"-(Pair N.ae2570aa95.out" new file mode 100644 index 0000000000000000000000000000000000000000..f606170a5fac8bb563a5030c90e4a567e65258c5 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None {})-\"hello\"-(Pair N.ae2570aa95.out" @@ -0,0 +1,42 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_and_update_big_map.tz-(Pair None {})-"hello"-(Pair None 0)-big_map_diff9] + +storage + (Pair None 0) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Unset map(0)["hello"] +trace + - location: 11 (remaining gas: 1039988.891 units remaining) + [ (Pair "hello" None {}) ] + - location: 13 (remaining gas: 1039988.781 units remaining) + [ "hello" @parameter + (Pair None {}) @storage ] + - location: 16 (remaining gas: 1039988.626 units remaining) + [ None + {} ] + - location: 15 (remaining gas: 1039988.581 units remaining) + [ None + {} ] + - location: 14 (remaining gas: 1039988.581 units remaining) + [ "hello" @parameter + None + {} ] + - location: -1 (remaining gas: 1039988.536 units remaining) + [ "hello" @parameter + None + {} ] + - location: 17 (remaining gas: 1039975.589 units remaining) + [ None + {} ] + - location: 18 (remaining gas: 1039975.514 units remaining) + [ (Pair None {}) ] + - location: 19 (remaining gas: 1039975.439 units remaining) + [ {} + (Pair None {}) ] + - location: 21 (remaining gas: 1039975.364 units remaining) + [ (Pair {} None {}) ] + - location: -1 (remaining gas: 1039975.319 units remaining) + [ (Pair {} None {}) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"tw.7085ccc339.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"tw.7085ccc339.out" new file mode 100644 index 0000000000000000000000000000000000000000..0e820e513a56d299429a2b138a5df31bd136fda7 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"tw.7085ccc339.out" @@ -0,0 +1,51 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt "1" "one" ; Elt "2" "two" } None)-"1"-(Pair 0 (Some "one"))-big_map_diff2] + +storage + (Pair 0 (Some "one")) +emitted operations + +big_map diff + New map(0) of type (big_map string string) + Set map(0)["2"] to "two" + Set map(0)["1"] to "one" +trace + - location: 11 (remaining gas: 1039965.019 units remaining) + [ (Pair "1" { Elt "1" "one" ; Elt "2" "two" } None) ] + - location: 12 (remaining gas: 1039964.939 units remaining) + [ (Pair "1" { Elt "1" "one" ; Elt "2" "two" } None) + (Pair "1" { Elt "1" "one" ; Elt "2" "two" } None) ] + - location: 13 (remaining gas: 1039964.859 units remaining) + [ "1" @parameter + (Pair "1" { Elt "1" "one" ; Elt "2" "two" } None) ] + - location: 17 (remaining gas: 1039964.674 units remaining) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } None) @storage ] + - location: 18 (remaining gas: 1039964.594 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } ] + - location: -1 (remaining gas: 1039964.549 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } ] + - location: 19 (remaining gas: 1039964.469 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: -1 (remaining gas: 1039964.424 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 14 (remaining gas: 1039964.424 units remaining) + [ "1" @parameter + { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 20 (remaining gas: 1039955.562 units remaining) + [ (Some "one") + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 21 (remaining gas: 1039955.492 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + (Some "one") ] + - location: 22 (remaining gas: 1039955.417 units remaining) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } (Some "one")) ] + - location: 23 (remaining gas: 1039955.342 units remaining) + [ {} + (Pair { Elt "1" "one" ; Elt "2" "two" } (Some "one")) ] + - location: 25 (remaining gas: 1039955.267 units remaining) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } (Some "one")) ] + - location: -1 (remaining gas: 1039955.222 units remaining) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } (Some "one")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt \"hello\" \"hi\" } None)-\"\".75aa05c5ef.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt \"hello\" \"hi\" } None)-\"\".75aa05c5ef.out" new file mode 100644 index 0000000000000000000000000000000000000000..15e73b3e622c6b96858b42909ce85c16473ff743 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt \"hello\" \"hi\" } None)-\"\".75aa05c5ef.out" @@ -0,0 +1,50 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt "hello" "hi" } None)-""-(Pair 0 None)-big_map_diff1] + +storage + (Pair 0 None) +emitted operations + +big_map diff + New map(0) of type (big_map string string) + Set map(0)["hello"] to "hi" +trace + - location: 11 (remaining gas: 1039970.497 units remaining) + [ (Pair "" { Elt "hello" "hi" } None) ] + - location: 12 (remaining gas: 1039970.417 units remaining) + [ (Pair "" { Elt "hello" "hi" } None) + (Pair "" { Elt "hello" "hi" } None) ] + - location: 13 (remaining gas: 1039970.337 units remaining) + [ "" @parameter + (Pair "" { Elt "hello" "hi" } None) ] + - location: 17 (remaining gas: 1039970.152 units remaining) + [ (Pair { Elt "hello" "hi" } None) @storage ] + - location: 18 (remaining gas: 1039970.072 units remaining) + [ { Elt "hello" "hi" } ] + - location: -1 (remaining gas: 1039970.027 units remaining) + [ { Elt "hello" "hi" } ] + - location: 19 (remaining gas: 1039969.947 units remaining) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: -1 (remaining gas: 1039969.902 units remaining) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 14 (remaining gas: 1039969.902 units remaining) + [ "" @parameter + { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 20 (remaining gas: 1039961.042 units remaining) + [ None + { Elt "hello" "hi" } ] + - location: 21 (remaining gas: 1039960.972 units remaining) + [ { Elt "hello" "hi" } + None ] + - location: 22 (remaining gas: 1039960.897 units remaining) + [ (Pair { Elt "hello" "hi" } None) ] + - location: 23 (remaining gas: 1039960.822 units remaining) + [ {} + (Pair { Elt "hello" "hi" } None) ] + - location: 25 (remaining gas: 1039960.747 units remaining) + [ (Pair {} { Elt "hello" "hi" } None) ] + - location: -1 (remaining gas: 1039960.702 units remaining) + [ (Pair {} { Elt "hello" "hi" } None) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt \"hello\" \"hi\" } None)-\"h.ce376412b0.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt \"hello\" \"hi\" } None)-\"h.ce376412b0.out" new file mode 100644 index 0000000000000000000000000000000000000000..b66739363dfb453b6308d1e035189a2aeb456e36 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt \"hello\" \"hi\" } None)-\"h.ce376412b0.out" @@ -0,0 +1,50 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[get_big_map_value.tz-(Pair { Elt "hello" "hi" } None)-"hello"-(Pair 0 (Some "hi"))-big_map_diff0] + +storage + (Pair 0 (Some "hi")) +emitted operations + +big_map diff + New map(0) of type (big_map string string) + Set map(0)["hello"] to "hi" +trace + - location: 11 (remaining gas: 1039970.447 units remaining) + [ (Pair "hello" { Elt "hello" "hi" } None) ] + - location: 12 (remaining gas: 1039970.367 units remaining) + [ (Pair "hello" { Elt "hello" "hi" } None) + (Pair "hello" { Elt "hello" "hi" } None) ] + - location: 13 (remaining gas: 1039970.287 units remaining) + [ "hello" @parameter + (Pair "hello" { Elt "hello" "hi" } None) ] + - location: 17 (remaining gas: 1039970.102 units remaining) + [ (Pair { Elt "hello" "hi" } None) @storage ] + - location: 18 (remaining gas: 1039970.022 units remaining) + [ { Elt "hello" "hi" } ] + - location: -1 (remaining gas: 1039969.977 units remaining) + [ { Elt "hello" "hi" } ] + - location: 19 (remaining gas: 1039969.897 units remaining) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: -1 (remaining gas: 1039969.852 units remaining) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 14 (remaining gas: 1039969.852 units remaining) + [ "hello" @parameter + { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 20 (remaining gas: 1039956.986 units remaining) + [ (Some "hi") + { Elt "hello" "hi" } ] + - location: 21 (remaining gas: 1039956.916 units remaining) + [ { Elt "hello" "hi" } + (Some "hi") ] + - location: 22 (remaining gas: 1039956.841 units remaining) + [ (Pair { Elt "hello" "hi" } (Some "hi")) ] + - location: 23 (remaining gas: 1039956.766 units remaining) + [ {} + (Pair { Elt "hello" "hi" } (Some "hi")) ] + - location: 25 (remaining gas: 1039956.691 units remaining) + [ (Pair {} { Elt "hello" "hi" } (Some "hi")) ] + - location: -1 (remaining gas: 1039956.646 units remaining) + [ (Pair {} { Elt "hello" "hi" } (Some "hi")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .0689a9f5c7.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .0689a9f5c7.out" new file mode 100644 index 0000000000000000000000000000000000000000..463daf9c717cb1fabb1db28ad65c80a50d06b767 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .0689a9f5c7.out" @@ -0,0 +1,54 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)-{ Elt "2" None }-(Pair 0 Unit)-big_map_diff7] + +storage + (Pair 0 Unit) +emitted operations + +big_map diff + New map(0) of type (big_map string string) + Unset map(0)["2"] + Set map(0)["1"] to "one" +trace + - location: 13 (remaining gas: 1039967.259 units remaining) + [ (Pair { Elt "2" None } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (remaining gas: 1039967.149 units remaining) + [ { Elt "2" None } @parameter + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) @storage ] + - location: 18 (remaining gas: 1039966.994 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 17 (remaining gas: 1039966.949 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (remaining gas: 1039966.949 units remaining) + [ { Elt "2" None } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: -1 (remaining gas: 1039966.904 units remaining) + [ { Elt "2" None } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (remaining gas: 1039966.674 units remaining) + [ "2" @key + None @elt + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (remaining gas: 1039957.806 units remaining) + [ { Elt "1" "one" } + Unit ] + - location: -1 (remaining gas: 1039957.761 units remaining) + [ { Elt "1" "one" } + Unit ] + - location: 19 (remaining gas: 1039957.761 units remaining) + [ { Elt "1" "one" } + Unit ] + - location: 23 (remaining gas: 1039957.686 units remaining) + [ (Pair { Elt "1" "one" } Unit) ] + - location: 24 (remaining gas: 1039957.611 units remaining) + [ {} + (Pair { Elt "1" "one" } Unit) ] + - location: 26 (remaining gas: 1039957.536 units remaining) + [ (Pair {} { Elt "1" "one" } Unit) ] + - location: -1 (remaining gas: 1039957.491 units remaining) + [ (Pair {} { Elt "1" "one" } Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .28027e7c51.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .28027e7c51.out" new file mode 100644 index 0000000000000000000000000000000000000000..af5a79b61cbb307cf2cf3d8ea892a016877a36a0 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .28027e7c51.out" @@ -0,0 +1,43 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)-{}-(Pair 0 Unit)-big_map_diff3] + +storage + (Pair 0 Unit) +emitted operations + +big_map diff + New map(0) of type (big_map string string) + Set map(0)["2"] to "two" + Set map(0)["1"] to "one" +trace + - location: 13 (remaining gas: 1039967.843 units remaining) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (remaining gas: 1039967.733 units remaining) + [ {} @parameter + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) @storage ] + - location: 18 (remaining gas: 1039967.578 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 17 (remaining gas: 1039967.533 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (remaining gas: 1039967.533 units remaining) + [ {} @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: -1 (remaining gas: 1039967.488 units remaining) + [ {} @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 19 (remaining gas: 1039967.378 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 23 (remaining gas: 1039967.303 units remaining) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 24 (remaining gas: 1039967.228 units remaining) + [ {} + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 26 (remaining gas: 1039967.153 units remaining) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: -1 (remaining gas: 1039967.108 units remaining) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .5b9b4f4add.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .5b9b4f4add.out" new file mode 100644 index 0000000000000000000000000000000000000000..168aafabcefc87557fa35251c7d2b198b3ad6426 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .5b9b4f4add.out" @@ -0,0 +1,54 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)-{ Elt "1" (Some "two") }-(Pair 0 Unit)-big_map_diff8] + +storage + (Pair 0 Unit) +emitted operations + +big_map diff + New map(0) of type (big_map string string) + Set map(0)["2"] to "two" + Set map(0)["1"] to "two" +trace + - location: 13 (remaining gas: 1039966.975 units remaining) + [ (Pair { Elt "1" (Some "two") } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (remaining gas: 1039966.865 units remaining) + [ { Elt "1" (Some "two") } @parameter + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) @storage ] + - location: 18 (remaining gas: 1039966.710 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 17 (remaining gas: 1039966.665 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (remaining gas: 1039966.665 units remaining) + [ { Elt "1" (Some "two") } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: -1 (remaining gas: 1039966.620 units remaining) + [ { Elt "1" (Some "two") } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (remaining gas: 1039966.390 units remaining) + [ "1" @key + (Some "two") @elt + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (remaining gas: 1039957.522 units remaining) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: -1 (remaining gas: 1039957.477 units remaining) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: 19 (remaining gas: 1039957.477 units remaining) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: 23 (remaining gas: 1039957.402 units remaining) + [ (Pair { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: 24 (remaining gas: 1039957.327 units remaining) + [ {} + (Pair { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: 26 (remaining gas: 1039957.252 units remaining) + [ (Pair {} { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: -1 (remaining gas: 1039957.207 units remaining) + [ (Pair {} { Elt "1" "two" ; Elt "2" "two" } Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .923a9b1a0c.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .923a9b1a0c.out" new file mode 100644 index 0000000000000000000000000000000000000000..0ab414039470102e52cf57fd35c888c5fa2a394e --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .923a9b1a0c.out" @@ -0,0 +1,54 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)-{ Elt "1" (Some "two") }-(Pair 0 Unit)-big_map_diff4] + +storage + (Pair 0 Unit) +emitted operations + +big_map diff + New map(0) of type (big_map string string) + Set map(0)["2"] to "two" + Set map(0)["1"] to "two" +trace + - location: 13 (remaining gas: 1039966.975 units remaining) + [ (Pair { Elt "1" (Some "two") } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (remaining gas: 1039966.865 units remaining) + [ { Elt "1" (Some "two") } @parameter + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) @storage ] + - location: 18 (remaining gas: 1039966.710 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 17 (remaining gas: 1039966.665 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (remaining gas: 1039966.665 units remaining) + [ { Elt "1" (Some "two") } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: -1 (remaining gas: 1039966.620 units remaining) + [ { Elt "1" (Some "two") } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (remaining gas: 1039966.390 units remaining) + [ "1" @key + (Some "two") @elt + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (remaining gas: 1039957.522 units remaining) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: -1 (remaining gas: 1039957.477 units remaining) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: 19 (remaining gas: 1039957.477 units remaining) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: 23 (remaining gas: 1039957.402 units remaining) + [ (Pair { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: 24 (remaining gas: 1039957.327 units remaining) + [ {} + (Pair { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: 26 (remaining gas: 1039957.252 units remaining) + [ (Pair {} { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: -1 (remaining gas: 1039957.207 units remaining) + [ (Pair {} { Elt "1" "two" ; Elt "2" "two" } Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .e075542e26.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .e075542e26.out" new file mode 100644 index 0000000000000000000000000000000000000000..19d4978b1a55c53fddceebc24cbcabaa3961d5fe --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .e075542e26.out" @@ -0,0 +1,55 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)-{ Elt "3" (Some "three") }-(Pair 0 Unit)-big_map_diff5] + +storage + (Pair 0 Unit) +emitted operations + +big_map diff + New map(0) of type (big_map string string) + Set map(0)["2"] to "two" + Set map(0)["3"] to "three" + Set map(0)["1"] to "one" +trace + - location: 13 (remaining gas: 1039966.955 units remaining) + [ (Pair { Elt "3" (Some "three") } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (remaining gas: 1039966.845 units remaining) + [ { Elt "3" (Some "three") } @parameter + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) @storage ] + - location: 18 (remaining gas: 1039966.690 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 17 (remaining gas: 1039966.645 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (remaining gas: 1039966.645 units remaining) + [ { Elt "3" (Some "three") } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: -1 (remaining gas: 1039966.600 units remaining) + [ { Elt "3" (Some "three") } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (remaining gas: 1039966.370 units remaining) + [ "3" @key + (Some "three") @elt + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (remaining gas: 1039957.502 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } + Unit ] + - location: -1 (remaining gas: 1039957.457 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } + Unit ] + - location: 19 (remaining gas: 1039957.457 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } + Unit ] + - location: 23 (remaining gas: 1039957.382 units remaining) + [ (Pair { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } Unit) ] + - location: 24 (remaining gas: 1039957.307 units remaining) + [ {} + (Pair { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } Unit) ] + - location: 26 (remaining gas: 1039957.232 units remaining) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } Unit) ] + - location: -1 (remaining gas: 1039957.187 units remaining) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .f2ff59db97.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .f2ff59db97.out" new file mode 100644 index 0000000000000000000000000000000000000000..fb64f4d5ce9ddbae078c51541f31273b08f513a5 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt \"1\" \"one\" ; Elt \"2\" \"two\" .f2ff59db97.out" @@ -0,0 +1,55 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test__big_map_contract_io[update_big_map.tz-(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)-{ Elt "3" None }-(Pair 0 Unit)-big_map_diff6] + +storage + (Pair 0 Unit) +emitted operations + +big_map diff + New map(0) of type (big_map string string) + Set map(0)["2"] to "two" + Unset map(0)["3"] + Set map(0)["1"] to "one" +trace + - location: 13 (remaining gas: 1039967.259 units remaining) + [ (Pair { Elt "3" None } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (remaining gas: 1039967.149 units remaining) + [ { Elt "3" None } @parameter + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) @storage ] + - location: 18 (remaining gas: 1039966.994 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 17 (remaining gas: 1039966.949 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (remaining gas: 1039966.949 units remaining) + [ { Elt "3" None } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: -1 (remaining gas: 1039966.904 units remaining) + [ { Elt "3" None } @parameter + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (remaining gas: 1039966.674 units remaining) + [ "3" @key + None @elt + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (remaining gas: 1039957.806 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: -1 (remaining gas: 1039957.761 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 19 (remaining gas: 1039957.761 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 23 (remaining gas: 1039957.686 units remaining) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 24 (remaining gas: 1039957.611 units remaining) + [ {} + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 26 (remaining gas: 1039957.536 units remaining) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: -1 (remaining gas: 1039957.491 units remaining) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[mul_overflow.tz-Unit-Left Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[mul_overflow.tz-Unit-Left Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..a345aea86313343d63ef7a53852f31fac73e22d3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[mul_overflow.tz-Unit-Left Unit].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_arithmetic_overflow[mul_overflow.tz-Unit-Left Unit] + +Runtime error in contract [CONTRACT_HASH]: + 01: parameter (or unit unit) ; + 02: storage unit ; + 03: code { CAR ; + 04: IF_LEFT + 05: { + 06: PUSH nat 922337203685477580700 ; + 07: PUSH mutez 10 ; + 08: MUL ; # FAILURE + 09: DROP + 10: } + 11: { + 12: PUSH mutez 10 ; + 13: PUSH nat 922337203685477580700 ; + 14: MUL ; # FAILURE + 15: DROP + 16: } ; + 17: + 18: NIL operation ; PAIR } + 19: +At line 8 characters 11 to 14, +unexpected arithmetic overflow +Fatal error: + error running script diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[mul_overflow.tz-Unit-Right Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[mul_overflow.tz-Unit-Right Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..e6edd9a1ac4671f0f7028bc772b654a0ef581b9e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[mul_overflow.tz-Unit-Right Unit].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_arithmetic_overflow[mul_overflow.tz-Unit-Right Unit] + +Runtime error in contract [CONTRACT_HASH]: + 01: parameter (or unit unit) ; + 02: storage unit ; + 03: code { CAR ; + 04: IF_LEFT + 05: { + 06: PUSH nat 922337203685477580700 ; + 07: PUSH mutez 10 ; + 08: MUL ; # FAILURE + 09: DROP + 10: } + 11: { + 12: PUSH mutez 10 ; + 13: PUSH nat 922337203685477580700 ; + 14: MUL ; # FAILURE + 15: DROP + 16: } ; + 17: + 18: NIL operation ; PAIR } + 19: +At line 14 characters 11 to 14, +unexpected arithmetic overflow +Fatal error: + error running script diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Left (Pair 1 257))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Left (Pair 1 257))].out new file mode 100644 index 0000000000000000000000000000000000000000..86efc866744d5eeeb4e5a4a06fc3f21ce53888dd --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Left (Pair 1 257))].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Left (Pair 1 257))] + +Runtime error in contract [CONTRACT_HASH]: + 01: parameter (or (pair nat nat) (pair nat nat)); + 02: storage (option nat); + 03: # this contract takes either (Left a b) and stores (a << b) + 04: # or (Right a b) and stores (a >> b). + 05: # i.e., in the first case, the first component shifted to the left by + 06: # the second, and the second case, component shifted to the right by + 07: # the second. + 08: code { CAR; + 09: IF_LEFT { + 10: UNPAIR; LSL; + 11: } + 12: { + 13: UNPAIR; LSR; + 14: }; + 15: SOME; + 16: NIL operation; + 17: PAIR; + 18: }; + 19: +At line 10 characters 25 to 28, +unexpected arithmetic overflow +Fatal error: + error running script diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Left (Pair 123 257))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Left (Pair 123 257))].out new file mode 100644 index 0000000000000000000000000000000000000000..17f5cadd1a2ef22e98de2300dbb221cbfd76a512 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Left (Pair 123 257))].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Left (Pair 123 257))] + +Runtime error in contract [CONTRACT_HASH]: + 01: parameter (or (pair nat nat) (pair nat nat)); + 02: storage (option nat); + 03: # this contract takes either (Left a b) and stores (a << b) + 04: # or (Right a b) and stores (a >> b). + 05: # i.e., in the first case, the first component shifted to the left by + 06: # the second, and the second case, component shifted to the right by + 07: # the second. + 08: code { CAR; + 09: IF_LEFT { + 10: UNPAIR; LSL; + 11: } + 12: { + 13: UNPAIR; LSR; + 14: }; + 15: SOME; + 16: NIL operation; + 17: PAIR; + 18: }; + 19: +At line 10 characters 25 to 28, +unexpected arithmetic overflow +Fatal error: + error running script diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Right (Pair 1 257))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Right (Pair 1 257))].out new file mode 100644 index 0000000000000000000000000000000000000000..7b1c7c5bc5b6383affd8a6be6e48a386f0da45e0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Right (Pair 1 257))].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Right (Pair 1 257))] + +Runtime error in contract [CONTRACT_HASH]: + 01: parameter (or (pair nat nat) (pair nat nat)); + 02: storage (option nat); + 03: # this contract takes either (Left a b) and stores (a << b) + 04: # or (Right a b) and stores (a >> b). + 05: # i.e., in the first case, the first component shifted to the left by + 06: # the second, and the second case, component shifted to the right by + 07: # the second. + 08: code { CAR; + 09: IF_LEFT { + 10: UNPAIR; LSL; + 11: } + 12: { + 13: UNPAIR; LSR; + 14: }; + 15: SOME; + 16: NIL operation; + 17: PAIR; + 18: }; + 19: +At line 13 characters 25 to 28, +unexpected arithmetic overflow +Fatal error: + error running script diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Right (Pair 123 257))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Right (Pair 123 257))].out new file mode 100644 index 0000000000000000000000000000000000000000..d623cf9ee098ec8bc76ccced75564847ad0890dc --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Right (Pair 123 257))].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_arithmetic_overflow[shifts.tz-None-(Right (Pair 123 257))] + +Runtime error in contract [CONTRACT_HASH]: + 01: parameter (or (pair nat nat) (pair nat nat)); + 02: storage (option nat); + 03: # this contract takes either (Left a b) and stores (a << b) + 04: # or (Right a b) and stores (a >> b). + 05: # i.e., in the first case, the first component shifted to the left by + 06: # the second, and the second case, component shifted to the right by + 07: # the second. + 08: code { CAR; + 09: IF_LEFT { + 10: UNPAIR; LSL; + 11: } + 12: { + 13: UNPAIR; LSR; + 14: }; + 15: SOME; + 16: NIL operation; + 17: PAIR; + 18: }; + 19: +At line 13 characters 25 to 28, +unexpected arithmetic overflow +Fatal error: + error running script diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[0.5].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[0.5].out new file mode 100644 index 0000000000000000000000000000000000000000..67fe8338041ade52565a8ced0d688aa600c20fd9 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[0.5].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_balance[0.5] + +storage + 500000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit 0) ] + - location: 7 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 8 (remaining gas: 1039779.619 units remaining) + [ 500000 @balance ] + - location: 9 (remaining gas: 1039779.544 units remaining) + [ {} + 500000 @balance ] + - location: 11 (remaining gas: 1039779.469 units remaining) + [ (Pair {} 500000) ] + - location: -1 (remaining gas: 1039779.424 units remaining) + [ (Pair {} 500000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[0].out new file mode 100644 index 0000000000000000000000000000000000000000..1569830e15c83d7b04bd64f3877fd9caea185785 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[0].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_balance[0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit 0) ] + - location: 7 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 8 (remaining gas: 1039779.619 units remaining) + [ 0 @balance ] + - location: 9 (remaining gas: 1039779.544 units remaining) + [ {} + 0 @balance ] + - location: 11 (remaining gas: 1039779.469 units remaining) + [ (Pair {} 0) ] + - location: -1 (remaining gas: 1039779.424 units remaining) + [ (Pair {} 0) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[1000].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[1000].out new file mode 100644 index 0000000000000000000000000000000000000000..a175f5e6ed36b8126bc707a407f2f4bfd6fc0b14 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[1000].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_balance[1000] + +storage + 1000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit 0) ] + - location: 7 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 8 (remaining gas: 1039779.619 units remaining) + [ 1000000000 @balance ] + - location: 9 (remaining gas: 1039779.544 units remaining) + [ {} + 1000000000 @balance ] + - location: 11 (remaining gas: 1039779.469 units remaining) + [ (Pair {} 1000000000) ] + - location: -1 (remaining gas: 1039779.424 units remaining) + [ (Pair {} 1000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[1].out new file mode 100644 index 0000000000000000000000000000000000000000..847783f28996f5a73b4152616dcbc4360acee600 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[1].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_balance[1] + +storage + 1000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit 0) ] + - location: 7 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 8 (remaining gas: 1039779.619 units remaining) + [ 1000000 @balance ] + - location: 9 (remaining gas: 1039779.544 units remaining) + [ {} + 1000000 @balance ] + - location: 11 (remaining gas: 1039779.469 units remaining) + [ (Pair {} 1000000) ] + - location: -1 (remaining gas: 1039779.424 units remaining) + [ (Pair {} 1000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[1e-06].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[1e-06].out new file mode 100644 index 0000000000000000000000000000000000000000..5a9a29067bd9107d36b056838b48ff2436a2489f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[1e-06].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_balance[1e-06] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit 0) ] + - location: 7 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 8 (remaining gas: 1039779.619 units remaining) + [ 1 @balance ] + - location: 9 (remaining gas: 1039779.544 units remaining) + [ {} + 1 @balance ] + - location: 11 (remaining gas: 1039779.469 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039779.424 units remaining) + [ (Pair {} 1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[5].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[5].out new file mode 100644 index 0000000000000000000000000000000000000000..380eafed12fcac4fe5af94e4960e09e59d14664a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[5].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_balance[5] + +storage + 5000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit 0) ] + - location: 7 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 8 (remaining gas: 1039779.619 units remaining) + [ 5000000 @balance ] + - location: 9 (remaining gas: 1039779.544 units remaining) + [ {} + 5000000 @balance ] + - location: 11 (remaining gas: 1039779.469 units remaining) + [ (Pair {} 5000000) ] + - location: -1 (remaining gas: 1039779.424 units remaining) + [ (Pair {} 5000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[8000000000000.0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[8000000000000.0].out new file mode 100644 index 0000000000000000000000000000000000000000..8e147503546e78e3445d7d5eaadb487092313aff --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_balance[8000000000000.0].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_balance[8000000000000.0] + +storage + 8000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit 0) ] + - location: 7 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 8 (remaining gas: 1039779.619 units remaining) + [ 8000000000000000000 @balance ] + - location: 9 (remaining gas: 1039779.544 units remaining) + [ {} + 8000000000000000000 @balance ] + - location: 11 (remaining gas: 1039779.469 units remaining) + [ (Pair {} 8000000000000000000) ] + - location: -1 (remaining gas: 1039779.424 units remaining) + [ (Pair {} 8000000000000000000) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }) )-(Right (Righ.4c10105111.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }) )-(Right (Righ.4c10105111.out" new file mode 100644 index 0000000000000000000000000000000000000000..cc56acee78377b1194d91f30c089c127ccb64f6b --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }) )-(Right (Righ.4c10105111.out" @@ -0,0 +1,80 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt "1" "one" } { Elt "2" "two" }) )-(Right (Right (Right (Left { Pair "3" "three" }))))-(Left (Pair 0 1))-big_map_diff4] + +storage + (Left (Pair 0 1)) +emitted operations + +big_map diff + New map(1) of type (big_map string string) + Set map(1)["2"] to "two" + New map(0) of type (big_map string string) + Set map(0)["3"] to "three" + Set map(0)["1"] to "one" +trace + - location: 42 (remaining gas: 1039903.779 units remaining) + [ (Pair (Right (Right (Right (Left { Pair "3" "three" })))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (remaining gas: 1039903.699 units remaining) + [ (Right (Right (Right (Left { Pair "3" "three" })))) @parameter + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) @storage ] + - location: 114 (remaining gas: 1039903.249 units remaining) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) @storage.left ] + - location: 112 (remaining gas: 1039903.204 units remaining) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) @storage.left ] + - location: 119 (remaining gas: 1039903.124 units remaining) + [ { Elt "1" "one" } + { Elt "2" "two" } ] + - location: -1 (remaining gas: 1039903.079 units remaining) + [ { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 110 (remaining gas: 1039903.079 units remaining) + [ { Pair "3" "three" } @parameter.right.right.right.add + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 122 (remaining gas: 1039902.462 units remaining) + [ "3" + "three" + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 125 (remaining gas: 1039902.312 units remaining) + [ (Some "three") + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 124 (remaining gas: 1039902.267 units remaining) + [ (Some "three") + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 123 (remaining gas: 1039902.267 units remaining) + [ "3" + (Some "three") + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 126 (remaining gas: 1039893.402 units remaining) + [ { Elt "1" "one" ; Elt "3" "three" } + { Elt "2" "two" } ] + - location: -1 (remaining gas: 1039893.357 units remaining) + [ { Elt "1" "one" ; Elt "3" "three" } + { Elt "2" "two" } ] + - location: 120 (remaining gas: 1039893.357 units remaining) + [ { Elt "1" "one" ; Elt "3" "three" } + { Elt "2" "two" } ] + - location: 127 (remaining gas: 1039893.282 units remaining) + [ (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" }) ] + - location: 128 (remaining gas: 1039893.207 units remaining) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: -1 (remaining gas: 1039893.162 units remaining) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 107 (remaining gas: 1039893.117 units remaining) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 64 (remaining gas: 1039893.072 units remaining) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 59 (remaining gas: 1039893.027 units remaining) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 151 (remaining gas: 1039892.952 units remaining) + [ {} + (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 153 (remaining gas: 1039892.877 units remaining) + [ (Pair {} (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" }))) ] + - location: -1 (remaining gas: 1039892.832 units remaining) + [ (Pair {} (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" }))) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Left Unit)-(.00a32294a4.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Left Unit)-(.00a32294a4.out" new file mode 100644 index 0000000000000000000000000000000000000000..7f4a05a5b48ab30482865c3b8ed8509d08f048bc --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Left Unit)-(.00a32294a4.out" @@ -0,0 +1,43 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))-(Left Unit)-(Left (Pair 0 1))-big_map_diff0] + +storage + (Left (Pair 0 1)) +emitted operations + +big_map diff + New map(1) of type (big_map string string) + Set map(1)["1"] to "one" + New map(0) of type (big_map string string) + Set map(0)["2"] to "two" +trace + - location: 42 (remaining gas: 1039905.682 units remaining) + [ (Pair (Left Unit) (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (remaining gas: 1039905.602 units remaining) + [ (Left Unit) @parameter + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) @storage ] + - location: 46 (remaining gas: 1039905.467 units remaining) + [ (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) @storage ] + - location: 49 (remaining gas: 1039905.332 units remaining) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) @storage.left ] + - location: 47 (remaining gas: 1039905.287 units remaining) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) @storage.left ] + - location: 54 (remaining gas: 1039905.207 units remaining) + [ { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 55 (remaining gas: 1039905.137 units remaining) + [ { Elt "2" "two" } + { Elt "1" "one" } ] + - location: 56 (remaining gas: 1039905.062 units remaining) + [ (Pair { Elt "2" "two" } { Elt "1" "one" }) ] + - location: 57 (remaining gas: 1039904.987 units remaining) + [ (Left (Pair { Elt "2" "two" } { Elt "1" "one" })) ] + - location: -1 (remaining gas: 1039904.942 units remaining) + [ (Left (Pair { Elt "2" "two" } { Elt "1" "one" })) ] + - location: 151 (remaining gas: 1039904.867 units remaining) + [ {} + (Left (Pair { Elt "2" "two" } { Elt "1" "one" })) ] + - location: 153 (remaining gas: 1039904.792 units remaining) + [ (Pair {} (Left (Pair { Elt "2" "two" } { Elt "1" "one" }))) ] + - location: -1 (remaining gas: 1039904.747 units remaining) + [ (Pair {} (Left (Pair { Elt "2" "two" } { Elt "1" "one" }))) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Right (Left .47f32b8f4c.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Right (Left .47f32b8f4c.out" new file mode 100644 index 0000000000000000000000000000000000000000..92fad91e97249ceb721a443bbb732d8f3e81eaab --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Right (Left .47f32b8f4c.out" @@ -0,0 +1,35 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))-(Right (Left (Left (Pair { Elt "3" "three" } { Elt "4" "four" }))))-(Left (Pair 0 1))-big_map_diff1] + +storage + (Left (Pair 0 1)) +emitted operations + +big_map diff + New map(1) of type (big_map string string) + Set map(1)["4"] to "four" + New map(0) of type (big_map string string) + Set map(0)["3"] to "three" +trace + - location: 42 (remaining gas: 1039884.434 units remaining) + [ (Pair (Right (Left (Left (Pair { Elt "3" "three" } { Elt "4" "four" })))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (remaining gas: 1039884.354 units remaining) + [ (Right (Left (Left (Pair { Elt "3" "three" } { Elt "4" "four" })))) @parameter + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) @storage ] + - location: 62 (remaining gas: 1039884.164 units remaining) + [ (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) @storage + (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) @parameter.right.reset ] + - location: 63 (remaining gas: 1039884.089 units remaining) + [ (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) @parameter.right.reset ] + - location: -1 (remaining gas: 1039884.044 units remaining) + [ (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) @parameter.right.reset ] + - location: 59 (remaining gas: 1039883.999 units remaining) + [ (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) ] + - location: 151 (remaining gas: 1039883.924 units remaining) + [ {} + (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) ] + - location: 153 (remaining gas: 1039883.849 units remaining) + [ (Pair {} (Left (Pair { Elt "3" "three" } { Elt "4" "four" }))) ] + - location: -1 (remaining gas: 1039883.804 units remaining) + [ (Pair {} (Left (Pair { Elt "3" "three" } { Elt "4" "four" }))) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Right (Left .8a6f480005.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Right (Left .8a6f480005.out" new file mode 100644 index 0000000000000000000000000000000000000000..7266ab4d16c31da9fd5b7ac101a9a3e90216bd2e --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Right (Left .8a6f480005.out" @@ -0,0 +1,31 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))-(Right (Left (Right Unit)))-(Right Unit)-big_map_diff2] + +storage + (Right Unit) +emitted operations + +big_map diff + +trace + - location: 42 (remaining gas: 1039904.452 units remaining) + [ (Pair (Right (Left (Right Unit))) (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (remaining gas: 1039904.372 units remaining) + [ (Right (Left (Right Unit))) @parameter + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) @storage ] + - location: 62 (remaining gas: 1039904.182 units remaining) + [ (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) @storage + (Right Unit) @parameter.right.reset ] + - location: 63 (remaining gas: 1039904.107 units remaining) + [ (Right Unit) @parameter.right.reset ] + - location: -1 (remaining gas: 1039904.062 units remaining) + [ (Right Unit) @parameter.right.reset ] + - location: 59 (remaining gas: 1039904.017 units remaining) + [ (Right Unit) ] + - location: 151 (remaining gas: 1039903.942 units remaining) + [ {} + (Right Unit) ] + - location: 153 (remaining gas: 1039903.867 units remaining) + [ (Pair {} (Right Unit)) ] + - location: -1 (remaining gas: 1039903.822 units remaining) + [ (Pair {} (Right Unit)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Right (Right.db0e6941b3.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Right (Right.db0e6941b3.out" new file mode 100644 index 0000000000000000000000000000000000000000..f7f2d81b41fe3df4244e482eef7552692290583e --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt \"1\" \"one\" } { Elt \"2\" \"two\" }))-(Right (Right.db0e6941b3.out" @@ -0,0 +1,74 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_big_map_magic[(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))-(Right (Right (Right (Right { "1" }))))-(Left (Pair 0 1))-big_map_diff5] + +storage + (Left (Pair 0 1)) +emitted operations + +big_map diff + New map(1) of type (big_map string string) + Set map(1)["2"] to "two" + New map(0) of type (big_map string string) + Unset map(0)["1"] +trace + - location: 42 (remaining gas: 1039904.323 units remaining) + [ (Pair (Right (Right (Right (Right { "1" })))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (remaining gas: 1039904.243 units remaining) + [ (Right (Right (Right (Right { "1" })))) @parameter + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) @storage ] + - location: 135 (remaining gas: 1039903.793 units remaining) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) @storage.left ] + - location: 133 (remaining gas: 1039903.748 units remaining) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) @storage.left ] + - location: 140 (remaining gas: 1039903.668 units remaining) + [ { Elt "1" "one" } + { Elt "2" "two" } ] + - location: -1 (remaining gas: 1039903.623 units remaining) + [ { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 131 (remaining gas: 1039903.623 units remaining) + [ { "1" } @parameter.right.right.right.rem + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 145 (remaining gas: 1039902.936 units remaining) + [ None + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 144 (remaining gas: 1039902.891 units remaining) + [ None + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 143 (remaining gas: 1039902.891 units remaining) + [ "1" @parameter.right.right.right.rem.elt + None + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 147 (remaining gas: 1039894.026 units remaining) + [ {} + { Elt "2" "two" } ] + - location: -1 (remaining gas: 1039893.981 units remaining) + [ {} + { Elt "2" "two" } ] + - location: 141 (remaining gas: 1039893.981 units remaining) + [ {} + { Elt "2" "two" } ] + - location: 148 (remaining gas: 1039893.906 units remaining) + [ (Pair {} { Elt "2" "two" }) ] + - location: 149 (remaining gas: 1039893.831 units remaining) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: -1 (remaining gas: 1039893.786 units remaining) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: 107 (remaining gas: 1039893.741 units remaining) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: 64 (remaining gas: 1039893.696 units remaining) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: 59 (remaining gas: 1039893.651 units remaining) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: 151 (remaining gas: 1039893.576 units remaining) + [ {} + (Left (Pair {} { Elt "2" "two" })) ] + - location: 153 (remaining gas: 1039893.501 units remaining) + [ (Pair {} (Left (Pair {} { Elt "2" "two" }))) ] + - location: -1 (remaining gas: 1039893.456 units remaining) + [ (Pair {} (Left (Pair {} { Elt "2" "two" }))) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Right Unit)-(Right (Right (Left (Pair { Pair \"foo\" \"bar\" } { P.79a01c2ffd.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Right Unit)-(Right (Right (Left (Pair { Pair \"foo\" \"bar\" } { P.79a01c2ffd.out" new file mode 100644 index 0000000000000000000000000000000000000000..ff93fe0ee95a8503f22bc6d235122facfe836eb1 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_big_map_magic[(Right Unit)-(Right (Right (Left (Pair { Pair \"foo\" \"bar\" } { P.79a01c2ffd.out" @@ -0,0 +1,128 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_big_map_magic[(Right Unit)-(Right (Right (Left (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" }) )))-(Left (Pair 0 1))-big_map_diff3] + +storage + (Left (Pair 0 1)) +emitted operations + +big_map diff + New map(1) of type (big_map string string) + Set map(1)["gaz"] to "baz" + New map(0) of type (big_map string string) + Set map(0)["foo"] to "bar" +trace + - location: 42 (remaining gas: 1039922.719 units remaining) + [ (Pair (Right (Right (Left (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" })))) (Right Unit)) ] + - location: 43 (remaining gas: 1039922.639 units remaining) + [ (Right (Right (Left (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" })))) @parameter + (Right Unit) @storage ] + - location: 75 (remaining gas: 1039922.249 units remaining) + [ Unit @storage.right ] + - location: 69 (remaining gas: 1039922.204 units remaining) + [ Unit @storage.right ] + - location: 76 (remaining gas: 1039922.129 units remaining) + [ ] + - location: -1 (remaining gas: 1039922.084 units remaining) + [ ] + - location: 67 (remaining gas: 1039922.084 units remaining) + [ (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" }) @parameter.right.right.import ] + - location: 77 (remaining gas: 1039922.004 units remaining) + [ { Pair "foo" "bar" } + { Pair "gaz" "baz" } ] + - location: 80 (remaining gas: 1039921.699 units remaining) + [ {} + { Pair "gaz" "baz" } ] + - location: 79 (remaining gas: 1039921.654 units remaining) + [ {} + { Pair "gaz" "baz" } ] + - location: 78 (remaining gas: 1039921.654 units remaining) + [ { Pair "foo" "bar" } + {} + { Pair "gaz" "baz" } ] + - location: 85 (remaining gas: 1039921.037 units remaining) + [ "foo" + "bar" + {} + { Pair "gaz" "baz" } ] + - location: 88 (remaining gas: 1039920.887 units remaining) + [ (Some "bar") + {} + { Pair "gaz" "baz" } ] + - location: 87 (remaining gas: 1039920.842 units remaining) + [ (Some "bar") + {} + { Pair "gaz" "baz" } ] + - location: 86 (remaining gas: 1039920.842 units remaining) + [ "foo" + (Some "bar") + {} + { Pair "gaz" "baz" } ] + - location: 89 (remaining gas: 1039909.978 units remaining) + [ { Elt "foo" "bar" } + { Pair "gaz" "baz" } ] + - location: -1 (remaining gas: 1039909.933 units remaining) + [ { Elt "foo" "bar" } + { Pair "gaz" "baz" } ] + - location: 83 (remaining gas: 1039909.933 units remaining) + [ { Elt "foo" "bar" } + { Pair "gaz" "baz" } ] + - location: 90 (remaining gas: 1039909.863 units remaining) + [ { Pair "gaz" "baz" } + { Elt "foo" "bar" } ] + - location: 93 (remaining gas: 1039909.558 units remaining) + [ {} + { Elt "foo" "bar" } ] + - location: 92 (remaining gas: 1039909.513 units remaining) + [ {} + { Elt "foo" "bar" } ] + - location: 91 (remaining gas: 1039909.513 units remaining) + [ { Pair "gaz" "baz" } + {} + { Elt "foo" "bar" } ] + - location: 98 (remaining gas: 1039908.896 units remaining) + [ "gaz" + "baz" + {} + { Elt "foo" "bar" } ] + - location: 101 (remaining gas: 1039908.746 units remaining) + [ (Some "baz") + {} + { Elt "foo" "bar" } ] + - location: 100 (remaining gas: 1039908.701 units remaining) + [ (Some "baz") + {} + { Elt "foo" "bar" } ] + - location: 99 (remaining gas: 1039908.701 units remaining) + [ "gaz" + (Some "baz") + {} + { Elt "foo" "bar" } ] + - location: 102 (remaining gas: 1039897.837 units remaining) + [ { Elt "gaz" "baz" } + { Elt "foo" "bar" } ] + - location: -1 (remaining gas: 1039897.792 units remaining) + [ { Elt "gaz" "baz" } + { Elt "foo" "bar" } ] + - location: 96 (remaining gas: 1039897.792 units remaining) + [ { Elt "gaz" "baz" } + { Elt "foo" "bar" } ] + - location: 103 (remaining gas: 1039897.722 units remaining) + [ { Elt "foo" "bar" } + { Elt "gaz" "baz" } ] + - location: 104 (remaining gas: 1039897.647 units remaining) + [ (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" }) ] + - location: 105 (remaining gas: 1039897.572 units remaining) + [ (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: -1 (remaining gas: 1039897.527 units remaining) + [ (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: 64 (remaining gas: 1039897.482 units remaining) + [ (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: 59 (remaining gas: 1039897.437 units remaining) + [ (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: 151 (remaining gas: 1039897.362 units remaining) + [ {} + (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: 153 (remaining gas: 1039897.287 units remaining) + [ (Pair {} (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" }))) ] + - location: -1 (remaining gas: 1039897.242 units remaining) + [ (Pair {} (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" }))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_check_signature.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_check_signature.out new file mode 100644 index 0000000000000000000000000000000000000000..e175c586df217db8215f1c2cfb15a0ac960b8f86 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_check_signature.out @@ -0,0 +1,233 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_check_signature + +storage + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039944.376 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 9 (remaining gas: 1039944.296 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 10 (remaining gas: 1039944.216 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 13 (remaining gas: 1039944.061 units remaining) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") @storage + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 14 (remaining gas: 1039943.981 units remaining) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") @storage + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") @storage + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 15 (remaining gas: 1039943.901 units remaining) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") @storage + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 18 (remaining gas: 1039943.746 units remaining) + [ "hello" + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 19 (remaining gas: 1039931.476 units remaining) + [ 0x05010000000568656c6c6f @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: -1 (remaining gas: 1039931.431 units remaining) + [ 0x05010000000568656c6c6f @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 16 (remaining gas: 1039931.431 units remaining) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000568656c6c6f @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: -1 (remaining gas: 1039931.386 units remaining) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000568656c6c6f @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 11 (remaining gas: 1039931.386 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000568656c6c6f @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 20 (remaining gas: 1039931.306 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" @parameter + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000568656c6c6f @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 21 (remaining gas: 1039661.263 units remaining) + [ True + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 23 (remaining gas: 1039661.163 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 28 (remaining gas: 1039661.083 units remaining) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") @storage ] + - location: 29 (remaining gas: 1039661.008 units remaining) + [ {} + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") @storage ] + - location: 31 (remaining gas: 1039660.933 units remaining) + [ (Pair {} + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: -1 (remaining gas: 1039660.888 units remaining) + [ (Pair {} + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + +Runtime error in contract [CONTRACT_HASH]: + 01: parameter key; + 02: storage (pair signature string); + 03: code { + 04: DUP; DUP; + 05: DIP{ CDR; DUP; CAR; + 06: DIP{CDR; PACK}}; + 07: CAR; CHECK_SIGNATURE; + 08: IF {} {FAIL} ; + 09: CDR; NIL operation ; PAIR}; + 10: + 11: +At line 8 characters 14 to 18, +script reached FAILWITH instruction +with Unit +trace + - location: 8 (remaining gas: 1039944.386 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 9 (remaining gas: 1039944.306 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 10 (remaining gas: 1039944.226 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 13 (remaining gas: 1039944.071 units remaining) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") @storage + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 14 (remaining gas: 1039943.991 units remaining) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") @storage + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") @storage + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 15 (remaining gas: 1039943.911 units remaining) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") @storage + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 18 (remaining gas: 1039943.756 units remaining) + [ "abcd" + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 19 (remaining gas: 1039931.486 units remaining) + [ 0x05010000000461626364 @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: -1 (remaining gas: 1039931.441 units remaining) + [ 0x05010000000461626364 @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 16 (remaining gas: 1039931.441 units remaining) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000461626364 @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: -1 (remaining gas: 1039931.396 units remaining) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000461626364 @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 11 (remaining gas: 1039931.396 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000461626364 @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 20 (remaining gas: 1039931.316 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" @parameter + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000461626364 @packed + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 21 (remaining gas: 1039661.274 units remaining) + [ False + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 26 (remaining gas: 1039661.114 units remaining) + [ Unit + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] +Fatal error: + error running script diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[abs.tz-Unit-0-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[abs.tz-Unit-0-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..c30d0156492bb8aad6e4f9291487db5bc7147b59 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[abs.tz-Unit-0-Unit].out @@ -0,0 +1,40 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[abs.tz-Unit-0-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039987.125 units remaining) + [ (Pair 0 Unit) ] + - location: 7 (remaining gas: 1039987.045 units remaining) + [ 0 @parameter ] + - location: 8 (remaining gas: 1039986.965 units remaining) + [ 0 @parameter + 0 @parameter ] + - location: 9 (remaining gas: 1039986.855 units remaining) + [ 0 + 0 @parameter ] + - location: 10 (remaining gas: 1039986.745 units remaining) + [ 0 + 0 @parameter ] + - location: 11 (remaining gas: 1039986.565 units remaining) + [ 0 ] + - location: 13 (remaining gas: 1039986.460 units remaining) + [ True ] + - location: 15 (remaining gas: 1039986.360 units remaining) + [ ] + - location: -1 (remaining gas: 1039986.315 units remaining) + [ ] + - location: 20 (remaining gas: 1039986.240 units remaining) + [ Unit ] + - location: 21 (remaining gas: 1039986.165 units remaining) + [ {} + Unit ] + - location: 23 (remaining gas: 1039986.090 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039986.045 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[abs.tz-Unit-12039123919239192312931-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[abs.tz-Unit-12039123919239192312931-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..0d98461cfa91c11851cfa635a0a6090a8adaac62 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[abs.tz-Unit-12039123919239192312931-Unit].out @@ -0,0 +1,40 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[abs.tz-Unit-12039123919239192312931-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039987.125 units remaining) + [ (Pair 12039123919239192312931 Unit) ] + - location: 7 (remaining gas: 1039987.045 units remaining) + [ 12039123919239192312931 @parameter ] + - location: 8 (remaining gas: 1039986.965 units remaining) + [ 12039123919239192312931 @parameter + 12039123919239192312931 @parameter ] + - location: 9 (remaining gas: 1039986.855 units remaining) + [ -12039123919239192312931 + 12039123919239192312931 @parameter ] + - location: 10 (remaining gas: 1039986.745 units remaining) + [ 12039123919239192312931 + 12039123919239192312931 @parameter ] + - location: 11 (remaining gas: 1039986.565 units remaining) + [ 0 ] + - location: 13 (remaining gas: 1039986.460 units remaining) + [ True ] + - location: 15 (remaining gas: 1039986.360 units remaining) + [ ] + - location: -1 (remaining gas: 1039986.315 units remaining) + [ ] + - location: 20 (remaining gas: 1039986.240 units remaining) + [ Unit ] + - location: 21 (remaining gas: 1039986.165 units remaining) + [ {} + Unit ] + - location: 23 (remaining gas: 1039986.090 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039986.045 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[abs.tz-Unit-948-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[abs.tz-Unit-948-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..8ba887afd83637304e02d7710bb5f1e84c902838 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[abs.tz-Unit-948-Unit].out @@ -0,0 +1,40 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[abs.tz-Unit-948-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039987.125 units remaining) + [ (Pair 948 Unit) ] + - location: 7 (remaining gas: 1039987.045 units remaining) + [ 948 @parameter ] + - location: 8 (remaining gas: 1039986.965 units remaining) + [ 948 @parameter + 948 @parameter ] + - location: 9 (remaining gas: 1039986.855 units remaining) + [ -948 + 948 @parameter ] + - location: 10 (remaining gas: 1039986.745 units remaining) + [ 948 + 948 @parameter ] + - location: 11 (remaining gas: 1039986.565 units remaining) + [ 0 ] + - location: 13 (remaining gas: 1039986.460 units remaining) + [ True ] + - location: 15 (remaining gas: 1039986.360 units remaining) + [ ] + - location: -1 (remaining gas: 1039986.315 units remaining) + [ ] + - location: 20 (remaining gas: 1039986.240 units remaining) + [ Unit ] + - location: 21 (remaining gas: 1039986.165 units remaining) + [ {} + Unit ] + - location: 23 (remaining gas: 1039986.090 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039986.045 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add.tz-Unit-Unit-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add.tz-Unit-Unit-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..0a3a83e60b0bc0ef92fafe042b4d812534d7e48a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add.tz-Unit-Unit-Unit].out @@ -0,0 +1,237 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add.tz-Unit-Unit-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039917.130 units remaining) + [ (Pair Unit Unit) ] + - location: 7 (remaining gas: 1039917.050 units remaining) + [ Unit @parameter ] + - location: 8 (remaining gas: 1039916.975 units remaining) + [ 2 + Unit @parameter ] + - location: 11 (remaining gas: 1039916.900 units remaining) + [ 2 + 2 + Unit @parameter ] + - location: 14 (remaining gas: 1039916.790 units remaining) + [ 4 + Unit @parameter ] + - location: 15 (remaining gas: 1039916.715 units remaining) + [ 4 + 4 + Unit @parameter ] + - location: 20 (remaining gas: 1039916.475 units remaining) + [ 0 + Unit @parameter ] + - location: 21 (remaining gas: 1039916.400 units remaining) + [ True + Unit @parameter ] + - location: -1 (remaining gas: 1039916.355 units remaining) + [ True + Unit @parameter ] + - location: 23 (remaining gas: 1039916.255 units remaining) + [ Unit @parameter ] + - location: -1 (remaining gas: 1039916.210 units remaining) + [ Unit @parameter ] + - location: 28 (remaining gas: 1039916.135 units remaining) + [ 2 + Unit @parameter ] + - location: 31 (remaining gas: 1039916.060 units remaining) + [ 2 + 2 + Unit @parameter ] + - location: 34 (remaining gas: 1039915.950 units remaining) + [ 4 + Unit @parameter ] + - location: 35 (remaining gas: 1039915.875 units remaining) + [ 4 + 4 + Unit @parameter ] + - location: 40 (remaining gas: 1039915.635 units remaining) + [ 0 + Unit @parameter ] + - location: 41 (remaining gas: 1039915.560 units remaining) + [ True + Unit @parameter ] + - location: -1 (remaining gas: 1039915.515 units remaining) + [ True + Unit @parameter ] + - location: 43 (remaining gas: 1039915.415 units remaining) + [ Unit @parameter ] + - location: -1 (remaining gas: 1039915.370 units remaining) + [ Unit @parameter ] + - location: 48 (remaining gas: 1039915.295 units remaining) + [ 2 + Unit @parameter ] + - location: 51 (remaining gas: 1039915.220 units remaining) + [ 2 + 2 + Unit @parameter ] + - location: 54 (remaining gas: 1039915.110 units remaining) + [ 4 + Unit @parameter ] + - location: 55 (remaining gas: 1039915.035 units remaining) + [ 4 + 4 + Unit @parameter ] + - location: 60 (remaining gas: 1039914.795 units remaining) + [ 0 + Unit @parameter ] + - location: 61 (remaining gas: 1039914.720 units remaining) + [ True + Unit @parameter ] + - location: -1 (remaining gas: 1039914.675 units remaining) + [ True + Unit @parameter ] + - location: 63 (remaining gas: 1039914.575 units remaining) + [ Unit @parameter ] + - location: -1 (remaining gas: 1039914.530 units remaining) + [ Unit @parameter ] + - location: 68 (remaining gas: 1039914.455 units remaining) + [ 2 + Unit @parameter ] + - location: 71 (remaining gas: 1039914.380 units remaining) + [ 2 + 2 + Unit @parameter ] + - location: 74 (remaining gas: 1039914.270 units remaining) + [ 4 + Unit @parameter ] + - location: 75 (remaining gas: 1039914.195 units remaining) + [ 4 + 4 + Unit @parameter ] + - location: 80 (remaining gas: 1039913.955 units remaining) + [ 0 + Unit @parameter ] + - location: 81 (remaining gas: 1039913.880 units remaining) + [ True + Unit @parameter ] + - location: -1 (remaining gas: 1039913.835 units remaining) + [ True + Unit @parameter ] + - location: 83 (remaining gas: 1039913.735 units remaining) + [ Unit @parameter ] + - location: -1 (remaining gas: 1039913.690 units remaining) + [ Unit @parameter ] + - location: 88 (remaining gas: 1039913.615 units remaining) + [ 2 + Unit @parameter ] + - location: 91 (remaining gas: 1039913.540 units remaining) + [ 2 + 2 + Unit @parameter ] + - location: 94 (remaining gas: 1039913.430 units remaining) + [ 4 + Unit @parameter ] + - location: 95 (remaining gas: 1039913.355 units remaining) + [ 4 + 4 + Unit @parameter ] + - location: 100 (remaining gas: 1039913.115 units remaining) + [ 0 + Unit @parameter ] + - location: 101 (remaining gas: 1039913.040 units remaining) + [ True + Unit @parameter ] + - location: -1 (remaining gas: 1039912.995 units remaining) + [ True + Unit @parameter ] + - location: 103 (remaining gas: 1039912.895 units remaining) + [ Unit @parameter ] + - location: -1 (remaining gas: 1039912.850 units remaining) + [ Unit @parameter ] + - location: 108 (remaining gas: 1039912.775 units remaining) + [ 60 + Unit @parameter ] + - location: 111 (remaining gas: 1039912.700 units remaining) + [ "2019-09-09T12:08:37Z" + 60 + Unit @parameter ] + - location: 114 (remaining gas: 1039912.590 units remaining) + [ "2019-09-09T12:09:37Z" + Unit @parameter ] + - location: 115 (remaining gas: 1039912.515 units remaining) + [ "2019-09-09T12:09:37Z" + "2019-09-09T12:09:37Z" + Unit @parameter ] + - location: 120 (remaining gas: 1039912.285 units remaining) + [ 0 + Unit @parameter ] + - location: 121 (remaining gas: 1039912.210 units remaining) + [ True + Unit @parameter ] + - location: -1 (remaining gas: 1039912.165 units remaining) + [ True + Unit @parameter ] + - location: 123 (remaining gas: 1039912.065 units remaining) + [ Unit @parameter ] + - location: -1 (remaining gas: 1039912.020 units remaining) + [ Unit @parameter ] + - location: 128 (remaining gas: 1039911.945 units remaining) + [ "2019-09-09T12:08:37Z" + Unit @parameter ] + - location: 131 (remaining gas: 1039911.870 units remaining) + [ 60 + "2019-09-09T12:08:37Z" + Unit @parameter ] + - location: 134 (remaining gas: 1039911.760 units remaining) + [ "2019-09-09T12:09:37Z" + Unit @parameter ] + - location: 135 (remaining gas: 1039911.685 units remaining) + [ "2019-09-09T12:09:37Z" + "2019-09-09T12:09:37Z" + Unit @parameter ] + - location: 140 (remaining gas: 1039911.455 units remaining) + [ 0 + Unit @parameter ] + - location: 141 (remaining gas: 1039911.380 units remaining) + [ True + Unit @parameter ] + - location: -1 (remaining gas: 1039911.335 units remaining) + [ True + Unit @parameter ] + - location: 143 (remaining gas: 1039911.235 units remaining) + [ Unit @parameter ] + - location: -1 (remaining gas: 1039911.190 units remaining) + [ Unit @parameter ] + - location: 148 (remaining gas: 1039911.115 units remaining) + [ 1000 + Unit @parameter ] + - location: 151 (remaining gas: 1039911.040 units remaining) + [ 1000 + 1000 + Unit @parameter ] + - location: 154 (remaining gas: 1039910.955 units remaining) + [ 2000 + Unit @parameter ] + - location: 155 (remaining gas: 1039910.880 units remaining) + [ 2000 + 2000 + Unit @parameter ] + - location: 160 (remaining gas: 1039910.686 units remaining) + [ 0 + Unit @parameter ] + - location: 161 (remaining gas: 1039910.611 units remaining) + [ True + Unit @parameter ] + - location: -1 (remaining gas: 1039910.566 units remaining) + [ True + Unit @parameter ] + - location: 163 (remaining gas: 1039910.466 units remaining) + [ Unit @parameter ] + - location: -1 (remaining gas: 1039910.421 units remaining) + [ Unit @parameter ] + - location: 168 (remaining gas: 1039910.346 units remaining) + [ {} + Unit @parameter ] + - location: 170 (remaining gas: 1039910.271 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039910.226 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x00 0x00-(Some 0x0000000.3c2de60480.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x00 0x00-(Some 0x0000000.3c2de60480.out new file mode 100644 index 0000000000000000000000000000000000000000..54443c9a071099bdccc0a8ba6bf9a01aee2d0376 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x00 0x00-(Some 0x0000000.3c2de60480.out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x00 0x00-(Some 0x0000000000000000000000000000000000000000000000000000000000000000)] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.020 units remaining) + [ (Pair (Pair 0x0000000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) + None) ] + - location: 10 (remaining gas: 1039991.940 units remaining) + [ (Pair 0x0000000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) @parameter ] + - location: 11 (remaining gas: 1039991.860 units remaining) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039991.630 units remaining) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 13 (remaining gas: 1039991.555 units remaining) + [ (Some 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 14 (remaining gas: 1039991.480 units remaining) + [ {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 16 (remaining gas: 1039991.405 units remaining) + [ (Pair {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000)) ] + - location: -1 (remaining gas: 1039991.360 units remaining) + [ (Pair {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x01 0x00-(Some 0x0100000.12b2c1172b.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x01 0x00-(Some 0x0100000.12b2c1172b.out new file mode 100644 index 0000000000000000000000000000000000000000..0378938b92355afeb271b3d9115f66d4a4c6b134 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x01 0x00-(Some 0x0100000.12b2c1172b.out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x01 0x00-(Some 0x0100000000000000000000000000000000000000000000000000000000000000)] + +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.020 units remaining) + [ (Pair (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) + None) ] + - location: 10 (remaining gas: 1039991.940 units remaining) + [ (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) @parameter ] + - location: 11 (remaining gas: 1039991.860 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039991.630 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 13 (remaining gas: 1039991.555 units remaining) + [ (Some 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 14 (remaining gas: 1039991.480 units remaining) + [ {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 16 (remaining gas: 1039991.405 units remaining) + [ (Pair {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000)) ] + - location: -1 (remaining gas: 1039991.360 units remaining) + [ (Pair {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x010000 0x00-(Some 0x010.0e44fc6f40.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x010000 0x00-(Some 0x010.0e44fc6f40.out new file mode 100644 index 0000000000000000000000000000000000000000..d2edbcb83a496e92f9d9e83349454e17b3557ad7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x010000 0x00-(Some 0x010.0e44fc6f40.out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x010000 0x00-(Some 0x0100000000000000000000000000000000000000000000000000000000000000)] + +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.020 units remaining) + [ (Pair (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) + None) ] + - location: 10 (remaining gas: 1039991.940 units remaining) + [ (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) @parameter ] + - location: 11 (remaining gas: 1039991.860 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039991.630 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 13 (remaining gas: 1039991.555 units remaining) + [ (Some 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 14 (remaining gas: 1039991.480 units remaining) + [ {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 16 (remaining gas: 1039991.405 units remaining) + [ (Pair {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000)) ] + - location: -1 (remaining gas: 1039991.360 units remaining) + [ (Pair {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x010000 0x010000-(Some 0.7e0ed229a3.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x010000 0x010000-(Some 0.7e0ed229a3.out new file mode 100644 index 0000000000000000000000000000000000000000..31f31e7f388b9f685960773e08b10dd944ae549c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x010000 0x010000-(Some 0.7e0ed229a3.out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_bls12_381_fr.tz-None-Pair 0x010000 0x010000-(Some 0x0200000000000000000000000000000000000000000000000000000000000000)] + +storage + (Some 0x0200000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.020 units remaining) + [ (Pair (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0100000000000000000000000000000000000000000000000000000000000000) + None) ] + - location: 10 (remaining gas: 1039991.940 units remaining) + [ (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0100000000000000000000000000000000000000000000000000000000000000) @parameter ] + - location: 11 (remaining gas: 1039991.860 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039991.630 units remaining) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 13 (remaining gas: 1039991.555 units remaining) + [ (Some 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: 14 (remaining gas: 1039991.480 units remaining) + [ {} + (Some 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: 16 (remaining gas: 1039991.405 units remaining) + [ (Pair {} + (Some 0x0200000000000000000000000000000000000000000000000000000000000000)) ] + - location: -1 (remaining gas: 1039991.360 units remaining) + [ (Pair {} + (Some 0x0200000000000000000000000000000000000000000000000000000000000000)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair -100 100)-(Some \"1970.7c1b1e4e5b.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair -100 100)-(Some \"1970.7c1b1e4e5b.out" new file mode 100644 index 0000000000000000000000000000000000000000..41acf6a956792385c0383201c52e404ad822ea62 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair -100 100)-(Some \"1970.7c1b1e4e5b.out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair -100 100)-(Some "1970-01-01T00:00:00Z")] + +storage + (Some "1970-01-01T00:00:00Z") +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.150 units remaining) + [ (Pair (Pair -100 "1970-01-01T00:01:40Z") None) ] + - location: 10 (remaining gas: 1039989.070 units remaining) + [ (Pair -100 "1970-01-01T00:01:40Z") @parameter ] + - location: 11 (remaining gas: 1039988.990 units remaining) + [ (Pair -100 "1970-01-01T00:01:40Z") @parameter + (Pair -100 "1970-01-01T00:01:40Z") @parameter ] + - location: 12 (remaining gas: 1039988.910 units remaining) + [ -100 + (Pair -100 "1970-01-01T00:01:40Z") @parameter ] + - location: 15 (remaining gas: 1039988.755 units remaining) + [ "1970-01-01T00:01:40Z" ] + - location: 14 (remaining gas: 1039988.710 units remaining) + [ "1970-01-01T00:01:40Z" ] + - location: 13 (remaining gas: 1039988.710 units remaining) + [ -100 + "1970-01-01T00:01:40Z" ] + - location: 16 (remaining gas: 1039988.600 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 17 (remaining gas: 1039988.525 units remaining) + [ (Some "1970-01-01T00:00:00Z") ] + - location: 18 (remaining gas: 1039988.450 units remaining) + [ {} + (Some "1970-01-01T00:00:00Z") ] + - location: 20 (remaining gas: 1039988.375 units remaining) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + - location: -1 (remaining gas: 1039988.330 units remaining) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair 0 \"1970-01-01T00:00:0.528ed42c01.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair 0 \"1970-01-01T00:00:0.528ed42c01.out" new file mode 100644 index 0000000000000000000000000000000000000000..89d4382e25425b4fcd86c824421ddf9ccbff183b --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair 0 \"1970-01-01T00:00:0.528ed42c01.out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair 0 "1970-01-01T00:00:00Z")-(Some "1970-01-01T00:00:00Z")] + +storage + (Some "1970-01-01T00:00:00Z") +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.020 units remaining) + [ (Pair (Pair 0 "1970-01-01T00:00:00Z") None) ] + - location: 10 (remaining gas: 1039988.940 units remaining) + [ (Pair 0 "1970-01-01T00:00:00Z") @parameter ] + - location: 11 (remaining gas: 1039988.860 units remaining) + [ (Pair 0 "1970-01-01T00:00:00Z") @parameter + (Pair 0 "1970-01-01T00:00:00Z") @parameter ] + - location: 12 (remaining gas: 1039988.780 units remaining) + [ 0 + (Pair 0 "1970-01-01T00:00:00Z") @parameter ] + - location: 15 (remaining gas: 1039988.625 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 14 (remaining gas: 1039988.580 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 13 (remaining gas: 1039988.580 units remaining) + [ 0 + "1970-01-01T00:00:00Z" ] + - location: 16 (remaining gas: 1039988.470 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 17 (remaining gas: 1039988.395 units remaining) + [ (Some "1970-01-01T00:00:00Z") ] + - location: 18 (remaining gas: 1039988.320 units remaining) + [ {} + (Some "1970-01-01T00:00:00Z") ] + - location: 20 (remaining gas: 1039988.245 units remaining) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + - location: -1 (remaining gas: 1039988.200 units remaining) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair 100 100)-(Some \"1970-.6566111ad2.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair 100 100)-(Some \"1970-.6566111ad2.out" new file mode 100644 index 0000000000000000000000000000000000000000..0bb1f77e6c2fad282410d4ae3e4ff848d2e3c2f0 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair 100 100)-(Some \"1970-.6566111ad2.out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_delta_timestamp.tz-None-(Pair 100 100)-(Some "1970-01-01T00:03:20Z")] + +storage + (Some "1970-01-01T00:03:20Z") +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.150 units remaining) + [ (Pair (Pair 100 "1970-01-01T00:01:40Z") None) ] + - location: 10 (remaining gas: 1039989.070 units remaining) + [ (Pair 100 "1970-01-01T00:01:40Z") @parameter ] + - location: 11 (remaining gas: 1039988.990 units remaining) + [ (Pair 100 "1970-01-01T00:01:40Z") @parameter + (Pair 100 "1970-01-01T00:01:40Z") @parameter ] + - location: 12 (remaining gas: 1039988.910 units remaining) + [ 100 + (Pair 100 "1970-01-01T00:01:40Z") @parameter ] + - location: 15 (remaining gas: 1039988.755 units remaining) + [ "1970-01-01T00:01:40Z" ] + - location: 14 (remaining gas: 1039988.710 units remaining) + [ "1970-01-01T00:01:40Z" ] + - location: 13 (remaining gas: 1039988.710 units remaining) + [ 100 + "1970-01-01T00:01:40Z" ] + - location: 16 (remaining gas: 1039988.600 units remaining) + [ "1970-01-01T00:03:20Z" ] + - location: 17 (remaining gas: 1039988.525 units remaining) + [ (Some "1970-01-01T00:03:20Z") ] + - location: 18 (remaining gas: 1039988.450 units remaining) + [ {} + (Some "1970-01-01T00:03:20Z") ] + - location: 20 (remaining gas: 1039988.375 units remaining) + [ (Pair {} (Some "1970-01-01T00:03:20Z")) ] + - location: -1 (remaining gas: 1039988.330 units remaining) + [ (Pair {} (Some "1970-01-01T00:03:20Z")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair \"1970-01-01T00:00:00Z.72c424f3da.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair \"1970-01-01T00:00:00Z.72c424f3da.out" new file mode 100644 index 0000000000000000000000000000000000000000..cc08a8a8f66124af4d77a24eed8db61d492e910b --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair \"1970-01-01T00:00:00Z.72c424f3da.out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair "1970-01-01T00:00:00Z" 0)-(Some "1970-01-01T00:00:00Z")] + +storage + (Some "1970-01-01T00:00:00Z") +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.020 units remaining) + [ (Pair (Pair "1970-01-01T00:00:00Z" 0) None) ] + - location: 10 (remaining gas: 1039988.940 units remaining) + [ (Pair "1970-01-01T00:00:00Z" 0) @parameter ] + - location: 11 (remaining gas: 1039988.860 units remaining) + [ (Pair "1970-01-01T00:00:00Z" 0) @parameter + (Pair "1970-01-01T00:00:00Z" 0) @parameter ] + - location: 12 (remaining gas: 1039988.780 units remaining) + [ "1970-01-01T00:00:00Z" + (Pair "1970-01-01T00:00:00Z" 0) @parameter ] + - location: 15 (remaining gas: 1039988.625 units remaining) + [ 0 ] + - location: 14 (remaining gas: 1039988.580 units remaining) + [ 0 ] + - location: 13 (remaining gas: 1039988.580 units remaining) + [ "1970-01-01T00:00:00Z" + 0 ] + - location: 16 (remaining gas: 1039988.470 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 17 (remaining gas: 1039988.395 units remaining) + [ (Some "1970-01-01T00:00:00Z") ] + - location: 18 (remaining gas: 1039988.320 units remaining) + [ {} + (Some "1970-01-01T00:00:00Z") ] + - location: 20 (remaining gas: 1039988.245 units remaining) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + - location: -1 (remaining gas: 1039988.200 units remaining) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair 100 -100)-(Some \"1970.7c4b12e9aa.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair 100 -100)-(Some \"1970.7c4b12e9aa.out" new file mode 100644 index 0000000000000000000000000000000000000000..b6618819c64f602c52ec8c4abaa43340807c0d26 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair 100 -100)-(Some \"1970.7c4b12e9aa.out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair 100 -100)-(Some "1970-01-01T00:00:00Z")] + +storage + (Some "1970-01-01T00:00:00Z") +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.150 units remaining) + [ (Pair (Pair "1970-01-01T00:01:40Z" -100) None) ] + - location: 10 (remaining gas: 1039989.070 units remaining) + [ (Pair "1970-01-01T00:01:40Z" -100) @parameter ] + - location: 11 (remaining gas: 1039988.990 units remaining) + [ (Pair "1970-01-01T00:01:40Z" -100) @parameter + (Pair "1970-01-01T00:01:40Z" -100) @parameter ] + - location: 12 (remaining gas: 1039988.910 units remaining) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" -100) @parameter ] + - location: 15 (remaining gas: 1039988.755 units remaining) + [ -100 ] + - location: 14 (remaining gas: 1039988.710 units remaining) + [ -100 ] + - location: 13 (remaining gas: 1039988.710 units remaining) + [ "1970-01-01T00:01:40Z" + -100 ] + - location: 16 (remaining gas: 1039988.600 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 17 (remaining gas: 1039988.525 units remaining) + [ (Some "1970-01-01T00:00:00Z") ] + - location: 18 (remaining gas: 1039988.450 units remaining) + [ {} + (Some "1970-01-01T00:00:00Z") ] + - location: 20 (remaining gas: 1039988.375 units remaining) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + - location: -1 (remaining gas: 1039988.330 units remaining) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair 100 100)-(Some \"1970-.af32743640.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair 100 100)-(Some \"1970-.af32743640.out" new file mode 100644 index 0000000000000000000000000000000000000000..12571910fb442964e698d3a903c8e693b70370e3 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair 100 100)-(Some \"1970-.af32743640.out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[add_timestamp_delta.tz-None-(Pair 100 100)-(Some "1970-01-01T00:03:20Z")] + +storage + (Some "1970-01-01T00:03:20Z") +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.150 units remaining) + [ (Pair (Pair "1970-01-01T00:01:40Z" 100) None) ] + - location: 10 (remaining gas: 1039989.070 units remaining) + [ (Pair "1970-01-01T00:01:40Z" 100) @parameter ] + - location: 11 (remaining gas: 1039988.990 units remaining) + [ (Pair "1970-01-01T00:01:40Z" 100) @parameter + (Pair "1970-01-01T00:01:40Z" 100) @parameter ] + - location: 12 (remaining gas: 1039988.910 units remaining) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" 100) @parameter ] + - location: 15 (remaining gas: 1039988.755 units remaining) + [ 100 ] + - location: 14 (remaining gas: 1039988.710 units remaining) + [ 100 ] + - location: 13 (remaining gas: 1039988.710 units remaining) + [ "1970-01-01T00:01:40Z" + 100 ] + - location: 16 (remaining gas: 1039988.600 units remaining) + [ "1970-01-01T00:03:20Z" ] + - location: 17 (remaining gas: 1039988.525 units remaining) + [ (Some "1970-01-01T00:03:20Z") ] + - location: 18 (remaining gas: 1039988.450 units remaining) + [ {} + (Some "1970-01-01T00:03:20Z") ] + - location: 20 (remaining gas: 1039988.375 units remaining) + [ (Pair {} (Some "1970-01-01T00:03:20Z")) ] + - location: -1 (remaining gas: 1039988.330 units remaining) + [ (Pair {} (Some "1970-01-01T00:03:20Z")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[address.tz-None-\"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5\"-.f9045c3a04.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[address.tz-None-\"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5\"-.f9045c3a04.out" new file mode 100644 index 0000000000000000000000000000000000000000..f37c600053c2ccd3da347fc81e4885b03ab2578a --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[address.tz-None-\"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5\"-.f9045c3a04.out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[address.tz-None-"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"-(Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5")] + +storage + (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039480.374 units remaining) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" None) ] + - location: 9 (remaining gas: 1039480.294 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @parameter ] + - location: 10 (remaining gas: 1039480.219 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @parameter.address ] + - location: 11 (remaining gas: 1039480.144 units remaining) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 12 (remaining gas: 1039480.069 units remaining) + [ {} + (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 14 (remaining gas: 1039479.994 units remaining) + [ (Pair {} (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5")) ] + - location: -1 (remaining gas: 1039479.949 units remaining) + [ (Pair {} (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5")) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair False False)-(Some False)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair False False)-(Some False)].out new file mode 100644 index 0000000000000000000000000000000000000000..127b2db0a0f5bf6b21e98d88c46b5d104396c06d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair False False)-(Some False)].out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair False False)-(Some False)] + +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039990.620 units remaining) + [ (Pair (Pair False False) None) ] + - location: 10 (remaining gas: 1039990.540 units remaining) + [ (Pair False False) @param ] + - location: 11 (remaining gas: 1039990.460 units remaining) + [ False + False ] + - location: 12 (remaining gas: 1039990.380 units remaining) + [ False @and ] + - location: 13 (remaining gas: 1039990.305 units remaining) + [ (Some False) @res ] + - location: 14 (remaining gas: 1039990.230 units remaining) + [ {} @noop + (Some False) @res ] + - location: 16 (remaining gas: 1039990.155 units remaining) + [ (Pair {} (Some False)) ] + - location: 17 (remaining gas: 1039990.075 units remaining) + [ {} @x + (Some False) @y ] + - location: 18 (remaining gas: 1039990 units remaining) + [ (Pair {} (Some False)) ] + - location: -1 (remaining gas: 1039989.955 units remaining) + [ (Pair {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair False True)-(Some False)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair False True)-(Some False)].out new file mode 100644 index 0000000000000000000000000000000000000000..390e4d20b3ea34dcc2dfd413d9171152a458cfc3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair False True)-(Some False)].out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair False True)-(Some False)] + +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039990.620 units remaining) + [ (Pair (Pair False True) None) ] + - location: 10 (remaining gas: 1039990.540 units remaining) + [ (Pair False True) @param ] + - location: 11 (remaining gas: 1039990.460 units remaining) + [ False + True ] + - location: 12 (remaining gas: 1039990.380 units remaining) + [ False @and ] + - location: 13 (remaining gas: 1039990.305 units remaining) + [ (Some False) @res ] + - location: 14 (remaining gas: 1039990.230 units remaining) + [ {} @noop + (Some False) @res ] + - location: 16 (remaining gas: 1039990.155 units remaining) + [ (Pair {} (Some False)) ] + - location: 17 (remaining gas: 1039990.075 units remaining) + [ {} @x + (Some False) @y ] + - location: 18 (remaining gas: 1039990 units remaining) + [ (Pair {} (Some False)) ] + - location: -1 (remaining gas: 1039989.955 units remaining) + [ (Pair {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair True False)-(Some False)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair True False)-(Some False)].out new file mode 100644 index 0000000000000000000000000000000000000000..4b977b8336425e71e2585637e795ae0412e8a0f8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair True False)-(Some False)].out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair True False)-(Some False)] + +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039990.620 units remaining) + [ (Pair (Pair True False) None) ] + - location: 10 (remaining gas: 1039990.540 units remaining) + [ (Pair True False) @param ] + - location: 11 (remaining gas: 1039990.460 units remaining) + [ True + False ] + - location: 12 (remaining gas: 1039990.380 units remaining) + [ False @and ] + - location: 13 (remaining gas: 1039990.305 units remaining) + [ (Some False) @res ] + - location: 14 (remaining gas: 1039990.230 units remaining) + [ {} @noop + (Some False) @res ] + - location: 16 (remaining gas: 1039990.155 units remaining) + [ (Pair {} (Some False)) ] + - location: 17 (remaining gas: 1039990.075 units remaining) + [ {} @x + (Some False) @y ] + - location: 18 (remaining gas: 1039990 units remaining) + [ (Pair {} (Some False)) ] + - location: -1 (remaining gas: 1039989.955 units remaining) + [ (Pair {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair True True)-(Some True)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair True True)-(Some True)].out new file mode 100644 index 0000000000000000000000000000000000000000..d06cc08273d25108b198f279d187f9cf0d0fc8dd --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair True True)-(Some True)].out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[and.tz-None-(Pair True True)-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039990.620 units remaining) + [ (Pair (Pair True True) None) ] + - location: 10 (remaining gas: 1039990.540 units remaining) + [ (Pair True True) @param ] + - location: 11 (remaining gas: 1039990.460 units remaining) + [ True + True ] + - location: 12 (remaining gas: 1039990.380 units remaining) + [ True @and ] + - location: 13 (remaining gas: 1039990.305 units remaining) + [ (Some True) @res ] + - location: 14 (remaining gas: 1039990.230 units remaining) + [ {} @noop + (Some True) @res ] + - location: 16 (remaining gas: 1039990.155 units remaining) + [ (Pair {} (Some True)) ] + - location: 17 (remaining gas: 1039990.075 units remaining) + [ {} @x + (Some True) @y ] + - location: 18 (remaining gas: 1039990 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039989.955 units remaining) + [ (Pair {} (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_binary.tz-Unit-Unit-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_binary.tz-Unit-Unit-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..43e5720016d500964643e3aed3f346fe3d775c52 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_binary.tz-Unit-Unit-Unit].out @@ -0,0 +1,103 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[and_binary.tz-Unit-Unit-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039955.820 units remaining) + [ (Pair Unit Unit) ] + - location: 7 (remaining gas: 1039955.745 units remaining) + [ ] + - location: 8 (remaining gas: 1039955.670 units remaining) + [ 5 ] + - location: 11 (remaining gas: 1039955.595 units remaining) + [ 6 + 5 ] + - location: 14 (remaining gas: 1039955.485 units remaining) + [ 4 ] + - location: 15 (remaining gas: 1039955.410 units remaining) + [ 4 + 4 ] + - location: 20 (remaining gas: 1039955.170 units remaining) + [ 0 ] + - location: 21 (remaining gas: 1039955.095 units remaining) + [ True ] + - location: -1 (remaining gas: 1039955.050 units remaining) + [ True ] + - location: 23 (remaining gas: 1039954.950 units remaining) + [ ] + - location: -1 (remaining gas: 1039954.905 units remaining) + [ ] + - location: 28 (remaining gas: 1039954.830 units remaining) + [ 6 ] + - location: 31 (remaining gas: 1039954.755 units remaining) + [ 5 + 6 ] + - location: 34 (remaining gas: 1039954.645 units remaining) + [ 4 ] + - location: 35 (remaining gas: 1039954.570 units remaining) + [ 4 + 4 ] + - location: 40 (remaining gas: 1039954.330 units remaining) + [ 0 ] + - location: 41 (remaining gas: 1039954.255 units remaining) + [ True ] + - location: -1 (remaining gas: 1039954.210 units remaining) + [ True ] + - location: 43 (remaining gas: 1039954.110 units remaining) + [ ] + - location: -1 (remaining gas: 1039954.065 units remaining) + [ ] + - location: 48 (remaining gas: 1039953.990 units remaining) + [ 12 ] + - location: 51 (remaining gas: 1039953.915 units remaining) + [ -1 + 12 ] + - location: 54 (remaining gas: 1039953.805 units remaining) + [ 12 ] + - location: 55 (remaining gas: 1039953.730 units remaining) + [ 12 + 12 ] + - location: 60 (remaining gas: 1039953.490 units remaining) + [ 0 ] + - location: 61 (remaining gas: 1039953.415 units remaining) + [ True ] + - location: -1 (remaining gas: 1039953.370 units remaining) + [ True ] + - location: 63 (remaining gas: 1039953.270 units remaining) + [ ] + - location: -1 (remaining gas: 1039953.225 units remaining) + [ ] + - location: 68 (remaining gas: 1039953.150 units remaining) + [ 12 ] + - location: 71 (remaining gas: 1039953.075 units remaining) + [ -5 + 12 ] + - location: 74 (remaining gas: 1039952.965 units remaining) + [ 8 ] + - location: 75 (remaining gas: 1039952.890 units remaining) + [ 8 + 8 ] + - location: 80 (remaining gas: 1039952.650 units remaining) + [ 0 ] + - location: 81 (remaining gas: 1039952.575 units remaining) + [ True ] + - location: -1 (remaining gas: 1039952.530 units remaining) + [ True ] + - location: 83 (remaining gas: 1039952.430 units remaining) + [ ] + - location: -1 (remaining gas: 1039952.385 units remaining) + [ ] + - location: 88 (remaining gas: 1039952.310 units remaining) + [ Unit ] + - location: 89 (remaining gas: 1039952.235 units remaining) + [ {} @noop + Unit ] + - location: 91 (remaining gas: 1039952.160 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039952.115 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair False False)-False].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair False False)-False].out new file mode 100644 index 0000000000000000000000000000000000000000..5db8b86efb51791f0ba97e3207225416926030d7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair False False)-False].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair False False)-False] + +storage + False +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.170 units remaining) + [ (Pair (Pair False False) False) ] + - location: 9 (remaining gas: 1039993.090 units remaining) + [ (Pair False False) @parameter ] + - location: 10 (remaining gas: 1039993.010 units remaining) + [ False + False ] + - location: 11 (remaining gas: 1039992.930 units remaining) + [ False @and ] + - location: 12 (remaining gas: 1039992.855 units remaining) + [ {} @noop + False @and ] + - location: 14 (remaining gas: 1039992.780 units remaining) + [ (Pair {} False) ] + - location: -1 (remaining gas: 1039992.735 units remaining) + [ (Pair {} False) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair False True)-False].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair False True)-False].out new file mode 100644 index 0000000000000000000000000000000000000000..8665ee48a8d24266f2bbd69e54d1c6972260107a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair False True)-False].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair False True)-False] + +storage + False +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.170 units remaining) + [ (Pair (Pair False True) False) ] + - location: 9 (remaining gas: 1039993.090 units remaining) + [ (Pair False True) @parameter ] + - location: 10 (remaining gas: 1039993.010 units remaining) + [ False + True ] + - location: 11 (remaining gas: 1039992.930 units remaining) + [ False @and ] + - location: 12 (remaining gas: 1039992.855 units remaining) + [ {} @noop + False @and ] + - location: 14 (remaining gas: 1039992.780 units remaining) + [ (Pair {} False) ] + - location: -1 (remaining gas: 1039992.735 units remaining) + [ (Pair {} False) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair True False)-False].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair True False)-False].out new file mode 100644 index 0000000000000000000000000000000000000000..732f02ba9c493f62fae6ba45ae957a12091f4b5f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair True False)-False].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair True False)-False] + +storage + False +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.170 units remaining) + [ (Pair (Pair True False) False) ] + - location: 9 (remaining gas: 1039993.090 units remaining) + [ (Pair True False) @parameter ] + - location: 10 (remaining gas: 1039993.010 units remaining) + [ True + False ] + - location: 11 (remaining gas: 1039992.930 units remaining) + [ False @and ] + - location: 12 (remaining gas: 1039992.855 units remaining) + [ {} @noop + False @and ] + - location: 14 (remaining gas: 1039992.780 units remaining) + [ (Pair {} False) ] + - location: -1 (remaining gas: 1039992.735 units remaining) + [ (Pair {} False) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair True True)-True].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair True True)-True].out new file mode 100644 index 0000000000000000000000000000000000000000..9667ea7bf1e30a6f99edec886dd514936a46e059 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair True True)-True].out @@ -0,0 +1,26 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[and_logical_1.tz-False-(Pair True True)-True] + +storage + True +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.170 units remaining) + [ (Pair (Pair True True) False) ] + - location: 9 (remaining gas: 1039993.090 units remaining) + [ (Pair True True) @parameter ] + - location: 10 (remaining gas: 1039993.010 units remaining) + [ True + True ] + - location: 11 (remaining gas: 1039992.930 units remaining) + [ True @and ] + - location: 12 (remaining gas: 1039992.855 units remaining) + [ {} @noop + True @and ] + - location: 14 (remaining gas: 1039992.780 units remaining) + [ (Pair {} True) ] + - location: -1 (remaining gas: 1039992.735 units remaining) + [ (Pair {} True) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[balance.tz-111-Unit-4000000000000].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[balance.tz-111-Unit-4000000000000].out new file mode 100644 index 0000000000000000000000000000000000000000..de8a6633efcfee2c595ea3e2fe78654ee1488dc4 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[balance.tz-111-Unit-4000000000000].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[balance.tz-111-Unit-4000000000000] + +storage + 4000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit 111) ] + - location: 7 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 8 (remaining gas: 1039779.619 units remaining) + [ 4000000000000 @balance ] + - location: 9 (remaining gas: 1039779.544 units remaining) + [ {} + 4000000000000 @balance ] + - location: 11 (remaining gas: 1039779.469 units remaining) + [ (Pair {} 4000000000000) ] + - location: -1 (remaining gas: 1039779.424 units remaining) + [ (Pair {} 4000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair 0 (S.4c96f27113.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair 0 (S.4c96f27113.out new file mode 100644 index 0000000000000000000000000000000000000000..5fda16302afbc1845112687db3f1d99adf92937c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair 0 (S.4c96f27113.out @@ -0,0 +1,46 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair 0 (Some False))1] + +storage + (Pair 0 (Some False)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[0] to 1 +trace + - location: 11 (remaining gas: 1039977.424 units remaining) + [ (Pair 1 { Elt 0 1 } None) ] + - location: 12 (remaining gas: 1039977.344 units remaining) + [ 1 @parameter + (Pair { Elt 0 1 } None) @storage ] + - location: 15 (remaining gas: 1039977.189 units remaining) + [ { Elt 0 1 } ] + - location: 16 (remaining gas: 1039977.109 units remaining) + [ { Elt 0 1 } + { Elt 0 1 } ] + - location: -1 (remaining gas: 1039977.064 units remaining) + [ { Elt 0 1 } + { Elt 0 1 } ] + - location: 13 (remaining gas: 1039977.064 units remaining) + [ 1 @parameter + { Elt 0 1 } + { Elt 0 1 } ] + - location: 17 (remaining gas: 1039968.208 units remaining) + [ False + { Elt 0 1 } ] + - location: 18 (remaining gas: 1039968.133 units remaining) + [ (Some False) + { Elt 0 1 } ] + - location: 19 (remaining gas: 1039968.063 units remaining) + [ { Elt 0 1 } + (Some False) ] + - location: 20 (remaining gas: 1039967.988 units remaining) + [ (Pair { Elt 0 1 } (Some False)) ] + - location: 21 (remaining gas: 1039967.913 units remaining) + [ {} + (Pair { Elt 0 1 } (Some False)) ] + - location: 23 (remaining gas: 1039967.838 units remaining) + [ (Pair {} { Elt 0 1 } (Some False)) ] + - location: -1 (remaining gas: 1039967.793 units remaining) + [ (Pair {} { Elt 0 1 } (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair 0 (S.7a576099dd.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair 0 (S.7a576099dd.out new file mode 100644 index 0000000000000000000000000000000000000000..2123eb89b17b49d6faefee0694e976bf48a38473 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair 0 (S.7a576099dd.out @@ -0,0 +1,46 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair 0 (Some False))0] + +storage + (Pair 0 (Some False)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[0] to 1 +trace + - location: 11 (remaining gas: 1039977.424 units remaining) + [ (Pair 1 { Elt 0 1 } None) ] + - location: 12 (remaining gas: 1039977.344 units remaining) + [ 1 @parameter + (Pair { Elt 0 1 } None) @storage ] + - location: 15 (remaining gas: 1039977.189 units remaining) + [ { Elt 0 1 } ] + - location: 16 (remaining gas: 1039977.109 units remaining) + [ { Elt 0 1 } + { Elt 0 1 } ] + - location: -1 (remaining gas: 1039977.064 units remaining) + [ { Elt 0 1 } + { Elt 0 1 } ] + - location: 13 (remaining gas: 1039977.064 units remaining) + [ 1 @parameter + { Elt 0 1 } + { Elt 0 1 } ] + - location: 17 (remaining gas: 1039968.208 units remaining) + [ False + { Elt 0 1 } ] + - location: 18 (remaining gas: 1039968.133 units remaining) + [ (Some False) + { Elt 0 1 } ] + - location: 19 (remaining gas: 1039968.063 units remaining) + [ { Elt 0 1 } + (Some False) ] + - location: 20 (remaining gas: 1039967.988 units remaining) + [ (Pair { Elt 0 1 } (Some False)) ] + - location: 21 (remaining gas: 1039967.913 units remaining) + [ {} + (Pair { Elt 0 1 } (Some False)) ] + - location: 23 (remaining gas: 1039967.838 units remaining) + [ (Pair {} { Elt 0 1 } (Some False)) ] + - location: -1 (remaining gas: 1039967.793 units remaining) + [ (Pair {} { Elt 0 1 } (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair 0 (S.a78f9cbe43.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair 0 (S.a78f9cbe43.out new file mode 100644 index 0000000000000000000000000000000000000000..c1ab6dd909ba3e4b45848ca6d082e0db5b8aa140 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair 0 (S.a78f9cbe43.out @@ -0,0 +1,46 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair 0 (Some True))0] + +storage + (Pair 0 (Some True)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[1] to 0 +trace + - location: 11 (remaining gas: 1039977.424 units remaining) + [ (Pair 1 { Elt 1 0 } None) ] + - location: 12 (remaining gas: 1039977.344 units remaining) + [ 1 @parameter + (Pair { Elt 1 0 } None) @storage ] + - location: 15 (remaining gas: 1039977.189 units remaining) + [ { Elt 1 0 } ] + - location: 16 (remaining gas: 1039977.109 units remaining) + [ { Elt 1 0 } + { Elt 1 0 } ] + - location: -1 (remaining gas: 1039977.064 units remaining) + [ { Elt 1 0 } + { Elt 1 0 } ] + - location: 13 (remaining gas: 1039977.064 units remaining) + [ 1 @parameter + { Elt 1 0 } + { Elt 1 0 } ] + - location: 17 (remaining gas: 1039968.208 units remaining) + [ True + { Elt 1 0 } ] + - location: 18 (remaining gas: 1039968.133 units remaining) + [ (Some True) + { Elt 1 0 } ] + - location: 19 (remaining gas: 1039968.063 units remaining) + [ { Elt 1 0 } + (Some True) ] + - location: 20 (remaining gas: 1039967.988 units remaining) + [ (Pair { Elt 1 0 } (Some True)) ] + - location: 21 (remaining gas: 1039967.913 units remaining) + [ {} + (Pair { Elt 1 0 } (Some True)) ] + - location: 23 (remaining gas: 1039967.838 units remaining) + [ (Pair {} { Elt 1 0 } (Some True)) ] + - location: -1 (remaining gas: 1039967.793 units remaining) + [ (Pair {} { Elt 1 0 } (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair 0 (S.eb161b3e7b.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair 0 (S.eb161b3e7b.out new file mode 100644 index 0000000000000000000000000000000000000000..20298fd61391dcc59941285c9b5801842198e095 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair 0 (S.eb161b3e7b.out @@ -0,0 +1,46 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair 0 (Some True))1] + +storage + (Pair 0 (Some True)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[1] to 0 +trace + - location: 11 (remaining gas: 1039977.424 units remaining) + [ (Pair 1 { Elt 1 0 } None) ] + - location: 12 (remaining gas: 1039977.344 units remaining) + [ 1 @parameter + (Pair { Elt 1 0 } None) @storage ] + - location: 15 (remaining gas: 1039977.189 units remaining) + [ { Elt 1 0 } ] + - location: 16 (remaining gas: 1039977.109 units remaining) + [ { Elt 1 0 } + { Elt 1 0 } ] + - location: -1 (remaining gas: 1039977.064 units remaining) + [ { Elt 1 0 } + { Elt 1 0 } ] + - location: 13 (remaining gas: 1039977.064 units remaining) + [ 1 @parameter + { Elt 1 0 } + { Elt 1 0 } ] + - location: 17 (remaining gas: 1039968.208 units remaining) + [ True + { Elt 1 0 } ] + - location: 18 (remaining gas: 1039968.133 units remaining) + [ (Some True) + { Elt 1 0 } ] + - location: 19 (remaining gas: 1039968.063 units remaining) + [ { Elt 1 0 } + (Some True) ] + - location: 20 (remaining gas: 1039967.988 units remaining) + [ (Pair { Elt 1 0 } (Some True)) ] + - location: 21 (remaining gas: 1039967.913 units remaining) + [ {} + (Pair { Elt 1 0 } (Some True)) ] + - location: 23 (remaining gas: 1039967.838 units remaining) + [ (Pair {} { Elt 1 0 } (Some True)) ] + - location: -1 (remaining gas: 1039967.793 units remaining) + [ (Pair {} { Elt 1 0 } (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1.09d8aca862.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1.09d8aca862.out new file mode 100644 index 0000000000000000000000000000000000000000..69f6005471ba2140836f3fa2ecf4786003d7552a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1.09d8aca862.out @@ -0,0 +1,47 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1-(Pair 0 (Some True))1] + +storage + (Pair 0 (Some True)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[1] to 4 + Set map(0)[2] to 11 +trace + - location: 11 (remaining gas: 1039967.964 units remaining) + [ (Pair 1 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (remaining gas: 1039967.884 units remaining) + [ 1 @parameter + (Pair { Elt 1 4 ; Elt 2 11 } None) @storage ] + - location: 15 (remaining gas: 1039967.729 units remaining) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (remaining gas: 1039967.649 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: -1 (remaining gas: 1039967.604 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (remaining gas: 1039967.604 units remaining) + [ 1 @parameter + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (remaining gas: 1039958.747 units remaining) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (remaining gas: 1039958.672 units remaining) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (remaining gas: 1039958.602 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (remaining gas: 1039958.527 units remaining) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (remaining gas: 1039958.452 units remaining) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (remaining gas: 1039958.377 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: -1 (remaining gas: 1039958.332 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1.8c67185afa.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1.8c67185afa.out new file mode 100644 index 0000000000000000000000000000000000000000..92d8d853decc488cf1dca65ce994c08b9172cf38 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1.8c67185afa.out @@ -0,0 +1,47 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1-(Pair 0 (Some True))0] + +storage + (Pair 0 (Some True)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[1] to 4 + Set map(0)[2] to 11 +trace + - location: 11 (remaining gas: 1039967.964 units remaining) + [ (Pair 1 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (remaining gas: 1039967.884 units remaining) + [ 1 @parameter + (Pair { Elt 1 4 ; Elt 2 11 } None) @storage ] + - location: 15 (remaining gas: 1039967.729 units remaining) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (remaining gas: 1039967.649 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: -1 (remaining gas: 1039967.604 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (remaining gas: 1039967.604 units remaining) + [ 1 @parameter + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (remaining gas: 1039958.747 units remaining) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (remaining gas: 1039958.672 units remaining) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (remaining gas: 1039958.602 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (remaining gas: 1039958.527 units remaining) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (remaining gas: 1039958.452 units remaining) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (remaining gas: 1039958.377 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: -1 (remaining gas: 1039958.332 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2.288a17ed5b.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2.288a17ed5b.out new file mode 100644 index 0000000000000000000000000000000000000000..001b3421976cc54b7a8bb07b60bbe70f95e32335 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2.288a17ed5b.out @@ -0,0 +1,47 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2-(Pair 0 (Some True))1] + +storage + (Pair 0 (Some True)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[1] to 4 + Set map(0)[2] to 11 +trace + - location: 11 (remaining gas: 1039967.964 units remaining) + [ (Pair 2 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (remaining gas: 1039967.884 units remaining) + [ 2 @parameter + (Pair { Elt 1 4 ; Elt 2 11 } None) @storage ] + - location: 15 (remaining gas: 1039967.729 units remaining) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (remaining gas: 1039967.649 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: -1 (remaining gas: 1039967.604 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (remaining gas: 1039967.604 units remaining) + [ 2 @parameter + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (remaining gas: 1039958.747 units remaining) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (remaining gas: 1039958.672 units remaining) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (remaining gas: 1039958.602 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (remaining gas: 1039958.527 units remaining) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (remaining gas: 1039958.452 units remaining) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (remaining gas: 1039958.377 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: -1 (remaining gas: 1039958.332 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2.359cf3d084.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2.359cf3d084.out new file mode 100644 index 0000000000000000000000000000000000000000..82f871bdeca417417758bd93e70f52cfac08de9c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2.359cf3d084.out @@ -0,0 +1,47 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2-(Pair 0 (Some True))0] + +storage + (Pair 0 (Some True)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[1] to 4 + Set map(0)[2] to 11 +trace + - location: 11 (remaining gas: 1039967.964 units remaining) + [ (Pair 2 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (remaining gas: 1039967.884 units remaining) + [ 2 @parameter + (Pair { Elt 1 4 ; Elt 2 11 } None) @storage ] + - location: 15 (remaining gas: 1039967.729 units remaining) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (remaining gas: 1039967.649 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: -1 (remaining gas: 1039967.604 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (remaining gas: 1039967.604 units remaining) + [ 2 @parameter + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (remaining gas: 1039958.747 units remaining) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (remaining gas: 1039958.672 units remaining) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (remaining gas: 1039958.602 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (remaining gas: 1039958.527 units remaining) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (remaining gas: 1039958.452 units remaining) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (remaining gas: 1039958.377 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: -1 (remaining gas: 1039958.332 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3.1c70ed3ee1.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3.1c70ed3ee1.out new file mode 100644 index 0000000000000000000000000000000000000000..7cd8073a4eb7c5149aea6e1f3830fca43230b012 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3.1c70ed3ee1.out @@ -0,0 +1,47 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3-(Pair 0 (Some False))1] + +storage + (Pair 0 (Some False)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[1] to 4 + Set map(0)[2] to 11 +trace + - location: 11 (remaining gas: 1039967.964 units remaining) + [ (Pair 3 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (remaining gas: 1039967.884 units remaining) + [ 3 @parameter + (Pair { Elt 1 4 ; Elt 2 11 } None) @storage ] + - location: 15 (remaining gas: 1039967.729 units remaining) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (remaining gas: 1039967.649 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: -1 (remaining gas: 1039967.604 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (remaining gas: 1039967.604 units remaining) + [ 3 @parameter + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (remaining gas: 1039958.747 units remaining) + [ False + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (remaining gas: 1039958.672 units remaining) + [ (Some False) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (remaining gas: 1039958.602 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + (Some False) ] + - location: 20 (remaining gas: 1039958.527 units remaining) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 21 (remaining gas: 1039958.452 units remaining) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 23 (remaining gas: 1039958.377 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: -1 (remaining gas: 1039958.332 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3.4df68c50c9.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3.4df68c50c9.out new file mode 100644 index 0000000000000000000000000000000000000000..310aa221ba0e63385ac99f6f0c07b1f63e5cf641 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3.4df68c50c9.out @@ -0,0 +1,47 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3-(Pair 0 (Some False))0] + +storage + (Pair 0 (Some False)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) + Set map(0)[1] to 4 + Set map(0)[2] to 11 +trace + - location: 11 (remaining gas: 1039967.964 units remaining) + [ (Pair 3 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (remaining gas: 1039967.884 units remaining) + [ 3 @parameter + (Pair { Elt 1 4 ; Elt 2 11 } None) @storage ] + - location: 15 (remaining gas: 1039967.729 units remaining) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (remaining gas: 1039967.649 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: -1 (remaining gas: 1039967.604 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (remaining gas: 1039967.604 units remaining) + [ 3 @parameter + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (remaining gas: 1039958.747 units remaining) + [ False + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (remaining gas: 1039958.672 units remaining) + [ (Some False) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (remaining gas: 1039958.602 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + (Some False) ] + - location: 20 (remaining gas: 1039958.527 units remaining) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 21 (remaining gas: 1039958.452 units remaining) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 23 (remaining gas: 1039958.377 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: -1 (remaining gas: 1039958.332 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair {} None)-1-(Pair 0 (Some False))0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair {} None)-1-(Pair 0 (Some False))0].out new file mode 100644 index 0000000000000000000000000000000000000000..9b9876a449a8adb008859e440ad6e25b309ad38f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair {} None)-1-(Pair 0 (Some False))0].out @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair {} None)-1-(Pair 0 (Some False))0] + +storage + (Pair 0 (Some False)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) +trace + - location: 11 (remaining gas: 1039986.730 units remaining) + [ (Pair 1 {} None) ] + - location: 12 (remaining gas: 1039986.650 units remaining) + [ 1 @parameter + (Pair {} None) @storage ] + - location: 15 (remaining gas: 1039986.495 units remaining) + [ {} ] + - location: 16 (remaining gas: 1039986.415 units remaining) + [ {} + {} ] + - location: -1 (remaining gas: 1039986.370 units remaining) + [ {} + {} ] + - location: 13 (remaining gas: 1039986.370 units remaining) + [ 1 @parameter + {} + {} ] + - location: 17 (remaining gas: 1039977.516 units remaining) + [ False + {} ] + - location: 18 (remaining gas: 1039977.441 units remaining) + [ (Some False) + {} ] + - location: 19 (remaining gas: 1039977.371 units remaining) + [ {} + (Some False) ] + - location: 20 (remaining gas: 1039977.296 units remaining) + [ (Pair {} (Some False)) ] + - location: 21 (remaining gas: 1039977.221 units remaining) + [ {} + (Pair {} (Some False)) ] + - location: 23 (remaining gas: 1039977.146 units remaining) + [ (Pair {} {} (Some False)) ] + - location: -1 (remaining gas: 1039977.101 units remaining) + [ (Pair {} {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair {} None)-1-(Pair 0 (Some False))1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair {} None)-1-(Pair 0 (Some False))1].out new file mode 100644 index 0000000000000000000000000000000000000000..4fc8f260c4ea8d5f5fa060c8c73ac36f704203a4 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair {} None)-1-(Pair 0 (Some False))1].out @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_nat.tz-(Pair {} None)-1-(Pair 0 (Some False))1] + +storage + (Pair 0 (Some False)) +emitted operations + +big_map diff + New map(0) of type (big_map nat nat) +trace + - location: 11 (remaining gas: 1039986.730 units remaining) + [ (Pair 1 {} None) ] + - location: 12 (remaining gas: 1039986.650 units remaining) + [ 1 @parameter + (Pair {} None) @storage ] + - location: 15 (remaining gas: 1039986.495 units remaining) + [ {} ] + - location: 16 (remaining gas: 1039986.415 units remaining) + [ {} + {} ] + - location: -1 (remaining gas: 1039986.370 units remaining) + [ {} + {} ] + - location: 13 (remaining gas: 1039986.370 units remaining) + [ 1 @parameter + {} + {} ] + - location: 17 (remaining gas: 1039977.516 units remaining) + [ False + {} ] + - location: 18 (remaining gas: 1039977.441 units remaining) + [ (Some False) + {} ] + - location: 19 (remaining gas: 1039977.371 units remaining) + [ {} + (Some False) ] + - location: 20 (remaining gas: 1039977.296 units remaining) + [ (Pair {} (Some False)) ] + - location: 21 (remaining gas: 1039977.221 units remaining) + [ {} + (Pair {} (Some False)) ] + - location: 23 (remaining gas: 1039977.146 units remaining) + [ (Pair {} {} (Some False)) ] + - location: -1 (remaining gas: 1039977.101 units remaining) + [ (Pair {} {} (Some False)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 1.712049bd7b.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 1.712049bd7b.out" new file mode 100644 index 0000000000000000000000000000000000000000..e442c81801ec7bf5798d6de5ac22e86050c9428e --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 1.712049bd7b.out" @@ -0,0 +1,47 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)-"baz"-(Pair 0 (Some False))] + +storage + (Pair 0 (Some False)) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["bar"] to 4 + Set map(0)["foo"] to 11 +trace + - location: 11 (remaining gas: 1039963.846 units remaining) + [ (Pair "baz" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (remaining gas: 1039963.766 units remaining) + [ "baz" @parameter + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) @storage ] + - location: 15 (remaining gas: 1039963.611 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (remaining gas: 1039963.531 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: -1 (remaining gas: 1039963.486 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (remaining gas: 1039963.486 units remaining) + [ "baz" @parameter + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (remaining gas: 1039952.621 units remaining) + [ False + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (remaining gas: 1039952.546 units remaining) + [ (Some False) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (remaining gas: 1039952.476 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some False) ] + - location: 20 (remaining gas: 1039952.401 units remaining) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: 21 (remaining gas: 1039952.326 units remaining) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: 23 (remaining gas: 1039952.251 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: -1 (remaining gas: 1039952.206 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 1.b18ef3a371.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 1.b18ef3a371.out" new file mode 100644 index 0000000000000000000000000000000000000000..08c56e36814808f6dc58b186028cc5dda6174f3e --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 1.b18ef3a371.out" @@ -0,0 +1,47 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)-"foo"-(Pair 0 (Some True))] + +storage + (Pair 0 (Some True)) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["bar"] to 4 + Set map(0)["foo"] to 11 +trace + - location: 11 (remaining gas: 1039963.846 units remaining) + [ (Pair "foo" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (remaining gas: 1039963.766 units remaining) + [ "foo" @parameter + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) @storage ] + - location: 15 (remaining gas: 1039963.611 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (remaining gas: 1039963.531 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: -1 (remaining gas: 1039963.486 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (remaining gas: 1039963.486 units remaining) + [ "foo" @parameter + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (remaining gas: 1039952.621 units remaining) + [ True + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (remaining gas: 1039952.546 units remaining) + [ (Some True) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (remaining gas: 1039952.476 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some True) ] + - location: 20 (remaining gas: 1039952.401 units remaining) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 21 (remaining gas: 1039952.326 units remaining) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 23 (remaining gas: 1039952.251 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: -1 (remaining gas: 1039952.206 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 1.d04a6af348.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 1.d04a6af348.out" new file mode 100644 index 0000000000000000000000000000000000000000..4c40a2295869bfd9f0feb9ccd85462e5bb8fccc1 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 1.d04a6af348.out" @@ -0,0 +1,47 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)-"bar"-(Pair 0 (Some True))] + +storage + (Pair 0 (Some True)) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["bar"] to 4 + Set map(0)["foo"] to 11 +trace + - location: 11 (remaining gas: 1039963.846 units remaining) + [ (Pair "bar" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (remaining gas: 1039963.766 units remaining) + [ "bar" @parameter + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) @storage ] + - location: 15 (remaining gas: 1039963.611 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (remaining gas: 1039963.531 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: -1 (remaining gas: 1039963.486 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (remaining gas: 1039963.486 units remaining) + [ "bar" @parameter + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (remaining gas: 1039952.621 units remaining) + [ True + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (remaining gas: 1039952.546 units remaining) + [ (Some True) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (remaining gas: 1039952.476 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some True) ] + - location: 20 (remaining gas: 1039952.401 units remaining) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 21 (remaining gas: 1039952.326 units remaining) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 23 (remaining gas: 1039952.251 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: -1 (remaining gas: 1039952.206 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"foo\" 0 } None)-\"foo\".1ae65b36c3.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"foo\" 0 } None)-\"foo\".1ae65b36c3.out" new file mode 100644 index 0000000000000000000000000000000000000000..ba1ab0cddeef3a0ccdd0b91d7729fe1d108d3c7a --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"foo\" 0 } None)-\"foo\".1ae65b36c3.out" @@ -0,0 +1,46 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt "foo" 0 } None)-"foo"-(Pair 0 (Some True))] + +storage + (Pair 0 (Some True)) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["foo"] to 0 +trace + - location: 11 (remaining gas: 1039975.328 units remaining) + [ (Pair "foo" { Elt "foo" 0 } None) ] + - location: 12 (remaining gas: 1039975.248 units remaining) + [ "foo" @parameter + (Pair { Elt "foo" 0 } None) @storage ] + - location: 15 (remaining gas: 1039975.093 units remaining) + [ { Elt "foo" 0 } ] + - location: 16 (remaining gas: 1039975.013 units remaining) + [ { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: -1 (remaining gas: 1039974.968 units remaining) + [ { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: 13 (remaining gas: 1039974.968 units remaining) + [ "foo" @parameter + { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: 17 (remaining gas: 1039964.104 units remaining) + [ True + { Elt "foo" 0 } ] + - location: 18 (remaining gas: 1039964.029 units remaining) + [ (Some True) + { Elt "foo" 0 } ] + - location: 19 (remaining gas: 1039963.959 units remaining) + [ { Elt "foo" 0 } + (Some True) ] + - location: 20 (remaining gas: 1039963.884 units remaining) + [ (Pair { Elt "foo" 0 } (Some True)) ] + - location: 21 (remaining gas: 1039963.809 units remaining) + [ {} + (Pair { Elt "foo" 0 } (Some True)) ] + - location: 23 (remaining gas: 1039963.734 units remaining) + [ (Pair {} { Elt "foo" 0 } (Some True)) ] + - location: -1 (remaining gas: 1039963.689 units remaining) + [ (Pair {} { Elt "foo" 0 } (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"foo\" 1 } None)-\"bar\".59ffcc6af5.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"foo\" 1 } None)-\"bar\".59ffcc6af5.out" new file mode 100644 index 0000000000000000000000000000000000000000..e745f76e404ca46d67be40dc927ba6a5bac076c9 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt \"foo\" 1 } None)-\"bar\".59ffcc6af5.out" @@ -0,0 +1,46 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair { Elt "foo" 1 } None)-"bar"-(Pair 0 (Some False))] + +storage + (Pair 0 (Some False)) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) + Set map(0)["foo"] to 1 +trace + - location: 11 (remaining gas: 1039975.328 units remaining) + [ (Pair "bar" { Elt "foo" 1 } None) ] + - location: 12 (remaining gas: 1039975.248 units remaining) + [ "bar" @parameter + (Pair { Elt "foo" 1 } None) @storage ] + - location: 15 (remaining gas: 1039975.093 units remaining) + [ { Elt "foo" 1 } ] + - location: 16 (remaining gas: 1039975.013 units remaining) + [ { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: -1 (remaining gas: 1039974.968 units remaining) + [ { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: 13 (remaining gas: 1039974.968 units remaining) + [ "bar" @parameter + { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: 17 (remaining gas: 1039964.104 units remaining) + [ False + { Elt "foo" 1 } ] + - location: 18 (remaining gas: 1039964.029 units remaining) + [ (Some False) + { Elt "foo" 1 } ] + - location: 19 (remaining gas: 1039963.959 units remaining) + [ { Elt "foo" 1 } + (Some False) ] + - location: 20 (remaining gas: 1039963.884 units remaining) + [ (Pair { Elt "foo" 1 } (Some False)) ] + - location: 21 (remaining gas: 1039963.809 units remaining) + [ {} + (Pair { Elt "foo" 1 } (Some False)) ] + - location: 23 (remaining gas: 1039963.734 units remaining) + [ (Pair {} { Elt "foo" 1 } (Some False)) ] + - location: -1 (remaining gas: 1039963.689 units remaining) + [ (Pair {} { Elt "foo" 1 } (Some False)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair {} None)-\"bar\"-(Pair 0 (Some False))].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair {} None)-\"bar\"-(Pair 0 (Some False))].out" new file mode 100644 index 0000000000000000000000000000000000000000..d29288469f56f2a22a4d612369a43edd0299fec5 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair {} None)-\"bar\"-(Pair 0 (Some False))].out" @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[big_map_mem_string.tz-(Pair {} None)-"bar"-(Pair 0 (Some False))] + +storage + (Pair 0 (Some False)) +emitted operations + +big_map diff + New map(0) of type (big_map string nat) +trace + - location: 11 (remaining gas: 1039986.686 units remaining) + [ (Pair "bar" {} None) ] + - location: 12 (remaining gas: 1039986.606 units remaining) + [ "bar" @parameter + (Pair {} None) @storage ] + - location: 15 (remaining gas: 1039986.451 units remaining) + [ {} ] + - location: 16 (remaining gas: 1039986.371 units remaining) + [ {} + {} ] + - location: -1 (remaining gas: 1039986.326 units remaining) + [ {} + {} ] + - location: 13 (remaining gas: 1039986.326 units remaining) + [ "bar" @parameter + {} + {} ] + - location: 17 (remaining gas: 1039975.464 units remaining) + [ False + {} ] + - location: 18 (remaining gas: 1039975.389 units remaining) + [ (Some False) + {} ] + - location: 19 (remaining gas: 1039975.319 units remaining) + [ {} + (Some False) ] + - location: 20 (remaining gas: 1039975.244 units remaining) + [ (Pair {} (Some False)) ] + - location: 21 (remaining gas: 1039975.169 units remaining) + [ {} + (Pair {} (Some False)) ] + - location: 23 (remaining gas: 1039975.094 units remaining) + [ (Pair {} {} (Some False)) ] + - location: -1 (remaining gas: 1039975.049 units remaining) + [ (Pair {} {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_push_bytes_not_padded.tz-None-Unit-(Some 0.9b6e8bcbd3.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_push_bytes_not_padded.tz-None-Unit-(Some 0.9b6e8bcbd3.out new file mode 100644 index 0000000000000000000000000000000000000000..92403acb6884653dc8fdbfaa87a8ce159c43156b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_push_bytes_not_padded.tz-None-Unit-(Some 0.9b6e8bcbd3.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_push_bytes_not_padded.tz-None-Unit-(Some 0x0000000000000000000000000000000000000000000000000000000000000000)] + +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.230 units remaining) + [ (Pair Unit None) ] + - location: 8 (remaining gas: 1039993.155 units remaining) + [ ] + - location: 9 (remaining gas: 1039993.080 units remaining) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.005 units remaining) + [ (Some 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 13 (remaining gas: 1039992.930 units remaining) + [ {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 15 (remaining gas: 1039992.855 units remaining) + [ (Pair {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000)) ] + - location: -1 (remaining gas: 1039992.810 units remaining) + [ (Pair {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_push_nat.tz-None-Unit-(Some 0x100000000000.d1219ca789.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_push_nat.tz-None-Unit-(Some 0x100000000000.d1219ca789.out new file mode 100644 index 0000000000000000000000000000000000000000..84de7b0c531f8ac3fb7adcb759b591e58e0a9da3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_push_nat.tz-None-Unit-(Some 0x100000000000.d1219ca789.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_push_nat.tz-None-Unit-(Some 0x1000000000000000000000000000000000000000000000000000000000000000)] + +storage + (Some 0x1000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.230 units remaining) + [ (Pair Unit None) ] + - location: 8 (remaining gas: 1039993.155 units remaining) + [ ] + - location: 9 (remaining gas: 1039993.080 units remaining) + [ 0x1000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.005 units remaining) + [ (Some 0x1000000000000000000000000000000000000000000000000000000000000000) ] + - location: 13 (remaining gas: 1039992.930 units remaining) + [ {} + (Some 0x1000000000000000000000000000000000000000000000000000000000000000) ] + - location: 15 (remaining gas: 1039992.855 units remaining) + [ (Pair {} + (Some 0x1000000000000000000000000000000000000000000000000000000000000000)) ] + - location: -1 (remaining gas: 1039992.810 units remaining) + [ (Pair {} + (Some 0x1000000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x00-0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x00-0].out new file mode 100644 index 0000000000000000000000000000000000000000..fe70822f3e6a6fbbe16a4b3260c4b624da3dd703 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x00-0].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x00-0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 @parameter ] + - location: 8 (remaining gas: 1039994.550 units remaining) + [ 0 ] + - location: 9 (remaining gas: 1039994.475 units remaining) + [ {} + 0 ] + - location: 11 (remaining gas: 1039994.400 units remaining) + [ (Pair {} 0) ] + - location: -1 (remaining gas: 1039994.355 units remaining) + [ (Pair {} 0) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x01-1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x01-1].out new file mode 100644 index 0000000000000000000000000000000000000000..bcde97927ebbc38f199ec6126eee9c3d04b54132 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x01-1].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x01-1] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @parameter ] + - location: 8 (remaining gas: 1039994.550 units remaining) + [ 1 ] + - location: 9 (remaining gas: 1039994.475 units remaining) + [ {} + 1 ] + - location: 11 (remaining gas: 1039994.400 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039994.355 units remaining) + [ (Pair {} 1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x28db8e57af88d9576acd181b89f2.7a85c336ff.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x28db8e57af88d9576acd181b89f2.7a85c336ff.out new file mode 100644 index 0000000000000000000000000000000000000000..f6dfbe1b91a1481dc383ebd98638ad2d72844c8e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x28db8e57af88d9576acd181b89f2.7a85c336ff.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0x28db8e57af88d9576acd181b89f24e50a89a6423f939026ed91349fc9af16c27-17832688077013577776524784494464728518213913213412866604053735695200962927400] + +storage + 17832688077013577776524784494464728518213913213412866604053735695200962927400 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 0x28db8e57af88d9576acd181b89f24e50a89a6423f939026ed91349fc9af16c27 0) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 0x28db8e57af88d9576acd181b89f24e50a89a6423f939026ed91349fc9af16c27 @parameter ] + - location: 8 (remaining gas: 1039994.550 units remaining) + [ 17832688077013577776524784494464728518213913213412866604053735695200962927400 ] + - location: 9 (remaining gas: 1039994.475 units remaining) + [ {} + 17832688077013577776524784494464728518213913213412866604053735695200962927400 ] + - location: 11 (remaining gas: 1039994.400 units remaining) + [ (Pair {} + 17832688077013577776524784494464728518213913213412866604053735695200962927400) ] + - location: -1 (remaining gas: 1039994.355 units remaining) + [ (Pair {} + 17832688077013577776524784494464728518213913213412866604053735695200962927400) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0xb9e8abf8dc324a010007addde986.b821eb26b3.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0xb9e8abf8dc324a010007addde986.b821eb26b3.out new file mode 100644 index 0000000000000000000000000000000000000000..f09cf072af5d2fea5e704c9f1244220befcc5356 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0xb9e8abf8dc324a010007addde986.b821eb26b3.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_int.tz-0-0xb9e8abf8dc324a010007addde986fe0f7c81fab16d26819d0534b7691c0b0719-11320265829256585830781521966149529460476767408210445238902869222031333517497] + +storage + 11320265829256585830781521966149529460476767408210445238902869222031333517497 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 0xb9e8abf8dc324a010007addde986fe0f7c81fab16d26819d0534b7691c0b0719 0) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 0xb9e8abf8dc324a010007addde986fe0f7c81fab16d26819d0534b7691c0b0719 @parameter ] + - location: 8 (remaining gas: 1039994.550 units remaining) + [ 11320265829256585830781521966149529460476767408210445238902869222031333517497 ] + - location: 9 (remaining gas: 1039994.475 units remaining) + [ {} + 11320265829256585830781521966149529460476767408210445238902869222031333517497 ] + - location: 11 (remaining gas: 1039994.400 units remaining) + [ (Pair {} + 11320265829256585830781521966149529460476767408210445238902869222031333517497) ] + - location: -1 (remaining gas: 1039994.355 units remaining) + [ (Pair {} + 11320265829256585830781521966149529460476767408210445238902869222031333517497) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_mutez.tz-0-0x10-16].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_mutez.tz-0-0x10-16].out new file mode 100644 index 0000000000000000000000000000000000000000..7535835be9f84abe706fa6ccf31aeffb259da3a3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_mutez.tz-0-0x10-16].out @@ -0,0 +1,34 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_to_mutez.tz-0-0x10-16] + +storage + 16 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039988.655 units remaining) + [ (Pair 0x1000000000000000000000000000000000000000000000000000000000000000 0) ] + - location: 7 (remaining gas: 1039988.575 units remaining) + [ 0x1000000000000000000000000000000000000000000000000000000000000000 @parameter ] + - location: 8 (remaining gas: 1039988.515 units remaining) + [ 16 ] + - location: 9 (remaining gas: 1039988.435 units remaining) + [ (Some 16) ] + - location: 16 (remaining gas: 1039988.300 units remaining) + [ 16 @some ] + - location: 10 (remaining gas: 1039988.255 units remaining) + [ 16 @some ] + - location: 17 (remaining gas: 1039988.180 units remaining) + [ 1 + 16 @some ] + - location: 20 (remaining gas: 1039987.817 units remaining) + [ 16 ] + - location: 21 (remaining gas: 1039987.742 units remaining) + [ {} + 16 ] + - location: 23 (remaining gas: 1039987.667 units remaining) + [ (Pair {} 16) ] + - location: -1 (remaining gas: 1039987.622 units remaining) + [ (Pair {} 16) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.0accef5bef.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.0accef5bef.out new file mode 100644 index 0000000000000000000000000000000000000000..257069e151f2ef60b6ddfca175142d06099995be --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.0accef5bef.out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000--42-0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73] + +storage + 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair -42 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ -42 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.0ecc537252.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.0ecc537252.out new file mode 100644 index 0000000000000000000000000000000000000000..adfe046941151ca57a1f093b5d6f4251eabfdf57 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.0ecc537252.out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000-2-0x0200000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0200000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 2 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 2 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.2229b767cd.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.2229b767cd.out new file mode 100644 index 0000000000000000000000000000000000000000..08d906966d308492b601ce59f1a5e42a3578693b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.2229b767cd.out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000--1-0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73] + +storage + 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair -1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ -1 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.2ff549b46b.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.2ff549b46b.out new file mode 100644 index 0000000000000000000000000000000000000000..67879487ebeb8cdfd0d2bfbf387ed168663e0f7a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.2ff549b46b.out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000-0-0x0000000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 0 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 0 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.bf8a711be6.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.bf8a711be6.out new file mode 100644 index 0000000000000000000000000000000000000000..3353f7ffb14d6556616d6831a9c4141220e66044 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.bf8a711be6.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000-52435875175126190479447740508185965837690552500527637822603658699938581184514-0x0100000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 52435875175126190479447740508185965837690552500527637822603658699938581184514 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.d41cbb044b.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.d41cbb044b.out new file mode 100644 index 0000000000000000000000000000000000000000..72c8a1e5e187324a1ddf63a891c252798ce3ebe0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000.d41cbb044b.out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000-1-0x0100000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 1 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x4147a5ad0a633e4880d2296f08ec5c1.a50412e458.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x4147a5ad0a633e4880d2296f08ec5c1.a50412e458.out new file mode 100644 index 0000000000000000000000000000000000000000..3ca884f4c0f546c51ac7c84971280879da57bbcb --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x4147a5ad0a633e4880d2296f08ec5c1.a50412e458.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f-22620284817922784902564672469917992996328211127984472897491698543785655336309-0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62] + +storage + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 22620284817922784902564672469917992996328211127984472897491698543785655336309 @parameter + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x5b0ecd0fa853810e356f1eb79721e80.f3a349c4a7.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x5b0ecd0fa853810e356f1eb79721e80.f3a349c4a7.out new file mode 100644 index 0000000000000000000000000000000000000000..13532e6db89a3d9b4f336ddeb8e44cf476de9dd1 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x5b0ecd0fa853810e356f1eb79721e80.f3a349c4a7.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f-33644916630334844239120348434626468649534186770809802792596996408934105684394-0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221] + +storage + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 33644916630334844239120348434626468649534186770809802792596996408934105684394 @parameter + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x8578be1766f92cd82c5e5135c374a03.1b9676e4c2.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x8578be1766f92cd82c5e5135c374a03.1b9676e4c2.out new file mode 100644 index 0000000000000000000000000000000000000000..02a97fd35feef82c08efaf6ce3f97414e1035625 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x8578be1766f92cd82c5e5135c374a03.1b9676e4c2.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d-69615968247920749285624776342583898043608129789011377475114141186797415307882-0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221] + +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 69615968247920749285624776342583898043608129789011377475114141186797415307882 @parameter + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x8578be1766f92cd82c5e5135c374a03.e966dc6de5.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x8578be1766f92cd82c5e5135c374a03.e966dc6de5.out new file mode 100644 index 0000000000000000000000000000000000000000..352cb73b99cca6a4ce26a22733b5002070f0b5f2 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x8578be1766f92cd82c5e5135c374a03.e966dc6de5.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_int.tz-0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d-17180093072794558806177035834397932205917577288483739652510482486858834123369-0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221] + +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 17180093072794558806177035834397932205917577288483739652510482486858834123369 @parameter + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.964835cc43.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.964835cc43.out new file mode 100644 index 0000000000000000000000000000000000000000..686fb2c7c62ed0bf496213de628a21fbfbb336dd --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.964835cc43.out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000000000000000000000000000000000000-1-0x0100000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 1 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.b25ea709fb.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.b25ea709fb.out new file mode 100644 index 0000000000000000000000000000000000000000..567a9daff812a696d28d7a3e87fe3f253e146d6f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.b25ea709fb.out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000000000000000000000000000000000000-0-0x0000000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 0 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 0 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.eae36753ea.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.eae36753ea.out new file mode 100644 index 0000000000000000000000000000000000000000..0781d4ac801ef6840103d62d8c3abfe44b20bbba --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.eae36753ea.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000000000000000000000000000000000000-52435875175126190479447740508185965837690552500527637822603658699938581184514-0x0100000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 52435875175126190479447740508185965837690552500527637822603658699938581184514 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.ee57dac8f7.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.ee57dac8f7.out new file mode 100644 index 0000000000000000000000000000000000000000..3dce74fdbad608d4edf52d87d47c96d8635a3980 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000.ee57dac8f7.out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x0100000000000000000000000000000000000000000000000000000000000000-2-0x0200000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0200000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 2 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 2 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x4147a5ad0a633e4880d2296f08ec5c1.928f6d4b93.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x4147a5ad0a633e4880d2296f08ec5c1.928f6d4b93.out new file mode 100644 index 0000000000000000000000000000000000000000..1aef1ddf77d272a31c005498733c09e2117db5a7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x4147a5ad0a633e4880d2296f08ec5c1.928f6d4b93.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f-22620284817922784902564672469917992996328211127984472897491698543785655336309-0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62] + +storage + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 22620284817922784902564672469917992996328211127984472897491698543785655336309 @parameter + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x5b0ecd0fa853810e356f1eb79721e80.bd5800f6b8.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x5b0ecd0fa853810e356f1eb79721e80.bd5800f6b8.out new file mode 100644 index 0000000000000000000000000000000000000000..ae311092b46bee73d2662e125a2059041e708f90 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x5b0ecd0fa853810e356f1eb79721e80.bd5800f6b8.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f-33644916630334844239120348434626468649534186770809802792596996408934105684394-0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221] + +storage + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 33644916630334844239120348434626468649534186770809802792596996408934105684394 @parameter + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x8578be1766f92cd82c5e5135c374a03.00e897789a.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x8578be1766f92cd82c5e5135c374a03.00e897789a.out new file mode 100644 index 0000000000000000000000000000000000000000..dcb79ad8bb6d54428db3c84845ca90656a323c41 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x8578be1766f92cd82c5e5135c374a03.00e897789a.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d-17180093072794558806177035834397932205917577288483739652510482486858834123369-0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221] + +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 17180093072794558806177035834397932205917577288483739652510482486858834123369 @parameter + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x8578be1766f92cd82c5e5135c374a03.a4697eaa13.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x8578be1766f92cd82c5e5135c374a03.a4697eaa13.out new file mode 100644 index 0000000000000000000000000000000000000000..f961d7ff10ccf72c82bb186febedd6b6e744f7ce --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x8578be1766f92cd82c5e5135c374a03.a4697eaa13.out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_fr_z_nat.tz-0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d-69615968247920749285624776342583898043608129789011377475114141186797415307882-0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221] + +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.690 units remaining) + [ (Pair 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (remaining gas: 1039994.610 units remaining) + [ 69615968247920749285624776342583898043608129789011377475114141186797415307882 @parameter + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage ] + - location: 8 (remaining gas: 1039994.200 units remaining) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 9 (remaining gas: 1039994.125 units remaining) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 11 (remaining gas: 1039994.050 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + - location: -1 (remaining gas: 1039994.005 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.0177355bbf.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.0177355bbf.out new file mode 100644 index 0000000000000000000000000000000000000000..ec6fae6c9c67afca1a5090e2df3f5f91b22dccc2 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.0177355bbf.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000-2-0x0200000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0200000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 2 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 2 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + 2 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.744166c609.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.744166c609.out new file mode 100644 index 0000000000000000000000000000000000000000..d101c47f824a3dcef70be30f632e4f6490ab6fdb --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.744166c609.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000--1-0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73] + +storage + 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair -1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ -1 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + -1 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.9f3c5cdc6a.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.9f3c5cdc6a.out new file mode 100644 index 0000000000000000000000000000000000000000..5c3f7ecfd83179071fe895275ee64533fed77469 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.9f3c5cdc6a.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000-0-0x0000000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 0 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 0 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + 0 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.a54cb341ba.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.a54cb341ba.out new file mode 100644 index 0000000000000000000000000000000000000000..65531ce5b9824f419594b95c96cf0499fa6bacd7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.a54cb341ba.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000--42-0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73] + +storage + 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair -42 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ -42 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + -42 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.b0dc584c94.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.b0dc584c94.out new file mode 100644 index 0000000000000000000000000000000000000000..87b8ef4fa291e861d47c8030764ec915bdd0fdaa --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.b0dc584c94.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000-1-0x0100000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 1 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + 1 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.bddcad090c.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.bddcad090c.out new file mode 100644 index 0000000000000000000000000000000000000000..747242157aced0070cf2fcaf3b2b7e8e00d4af3e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000.bddcad090c.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x0100000000000000000000000000000000000000000000000000000000000000-52435875175126190479447740508185965837690552500527637822603658699938581184514-0x0100000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 52435875175126190479447740508185965837690552500527637822603658699938581184514 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + 52435875175126190479447740508185965837690552500527637822603658699938581184514 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x4147a5ad0a633e4880d2296f08ec5c1.92c153eb47.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x4147a5ad0a633e4880d2296f08ec5c1.92c153eb47.out new file mode 100644 index 0000000000000000000000000000000000000000..1a602f50881a186dba5591351bd47db12ff01377 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x4147a5ad0a633e4880d2296f08ec5c1.92c153eb47.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f-22620284817922784902564672469917992996328211127984472897491698543785655336309-0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62] + +storage + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 22620284817922784902564672469917992996328211127984472897491698543785655336309 @parameter + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f @storage + 22620284817922784902564672469917992996328211127984472897491698543785655336309 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x5b0ecd0fa853810e356f1eb79721e80.290ab49d11.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x5b0ecd0fa853810e356f1eb79721e80.290ab49d11.out new file mode 100644 index 0000000000000000000000000000000000000000..1bfba25c12ec7861e3ec8973b47cc2ed26be88e7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x5b0ecd0fa853810e356f1eb79721e80.290ab49d11.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f-33644916630334844239120348434626468649534186770809802792596996408934105684394-0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221] + +storage + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 33644916630334844239120348434626468649534186770809802792596996408934105684394 @parameter + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f @storage + 33644916630334844239120348434626468649534186770809802792596996408934105684394 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x8578be1766f92cd82c5e5135c374a03.69f3589a06.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x8578be1766f92cd82c5e5135c374a03.69f3589a06.out new file mode 100644 index 0000000000000000000000000000000000000000..8e1d907aae4e0198d5295ec2de7508b30ccdd6c3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x8578be1766f92cd82c5e5135c374a03.69f3589a06.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d-17180093072794558806177035834397932205917577288483739652510482486858834123369-0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221] + +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 17180093072794558806177035834397932205917577288483739652510482486858834123369 @parameter + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage + 17180093072794558806177035834397932205917577288483739652510482486858834123369 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x8578be1766f92cd82c5e5135c374a03.fee3c5cf43.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x8578be1766f92cd82c5e5135c374a03.fee3c5cf43.out new file mode 100644 index 0000000000000000000000000000000000000000..5b7e0d2805b25af8f82f909473341c9aabcdc5aa --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x8578be1766f92cd82c5e5135c374a03.fee3c5cf43.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_int.tz-0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d-69615968247920749285624776342583898043608129789011377475114141186797415307882-0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221] + +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 69615968247920749285624776342583898043608129789011377475114141186797415307882 @parameter + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage + 69615968247920749285624776342583898043608129789011377475114141186797415307882 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.1bccc033e8.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.1bccc033e8.out new file mode 100644 index 0000000000000000000000000000000000000000..15776607a01a0733d8df98b3d96a1e18f9c9b250 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.1bccc033e8.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000000000000000000000000000000000000-52435875175126190479447740508185965837690552500527637822603658699938581184514-0x0100000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 52435875175126190479447740508185965837690552500527637822603658699938581184514 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + 52435875175126190479447740508185965837690552500527637822603658699938581184514 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.40958700fe.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.40958700fe.out new file mode 100644 index 0000000000000000000000000000000000000000..cd63cde9825ded598344b6cc777c93bb71350d2b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.40958700fe.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000000000000000000000000000000000000-0-0x0000000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 0 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 0 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + 0 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.6c62b03d78.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.6c62b03d78.out new file mode 100644 index 0000000000000000000000000000000000000000..4f39e85ea5c5156dce10c46bf88770f98187a1cd --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.6c62b03d78.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000000000000000000000000000000000000-1-0x0100000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 1 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + 1 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.d23f269341.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.d23f269341.out new file mode 100644 index 0000000000000000000000000000000000000000..122f744eb6963019c928899ed75edfea9abf65be --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000.d23f269341.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x0100000000000000000000000000000000000000000000000000000000000000-2-0x0200000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0200000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 2 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 2 @parameter + 0x0100000000000000000000000000000000000000000000000000000000000000 @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 @storage + 2 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x4147a5ad0a633e4880d2296f08ec5c1.927f808504.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x4147a5ad0a633e4880d2296f08ec5c1.927f808504.out new file mode 100644 index 0000000000000000000000000000000000000000..a1dc14d51c12062e3087d04b5f1ceaf37c455d24 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x4147a5ad0a633e4880d2296f08ec5c1.927f808504.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f-22620284817922784902564672469917992996328211127984472897491698543785655336309-0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62] + +storage + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 22620284817922784902564672469917992996328211127984472897491698543785655336309 @parameter + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f @storage + 22620284817922784902564672469917992996328211127984472897491698543785655336309 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x5b0ecd0fa853810e356f1eb79721e80.0c114c956a.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x5b0ecd0fa853810e356f1eb79721e80.0c114c956a.out new file mode 100644 index 0000000000000000000000000000000000000000..cf693514c393dce5fe20356f0fc6c65c694aa3b0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x5b0ecd0fa853810e356f1eb79721e80.0c114c956a.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f-33644916630334844239120348434626468649534186770809802792596996408934105684394-0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221] + +storage + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 33644916630334844239120348434626468649534186770809802792596996408934105684394 @parameter + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f @storage + 33644916630334844239120348434626468649534186770809802792596996408934105684394 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x8578be1766f92cd82c5e5135c374a03.03c4f38e68.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x8578be1766f92cd82c5e5135c374a03.03c4f38e68.out new file mode 100644 index 0000000000000000000000000000000000000000..cad520e95cc013147a383232c1f8de7cc9608e46 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x8578be1766f92cd82c5e5135c374a03.03c4f38e68.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d-69615968247920749285624776342583898043608129789011377475114141186797415307882-0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221] + +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 69615968247920749285624776342583898043608129789011377475114141186797415307882 @parameter + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage + 69615968247920749285624776342583898043608129789011377475114141186797415307882 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x8578be1766f92cd82c5e5135c374a03.8ed19cfdd9.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x8578be1766f92cd82c5e5135c374a03.8ed19cfdd9.out new file mode 100644 index 0000000000000000000000000000000000000000..c90531b0e3985881c3ade7178a6ab5701367cce1 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x8578be1766f92cd82c5e5135c374a03.8ed19cfdd9.out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[bls12_381_z_fr_nat.tz-0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d-17180093072794558806177035834397932205917577288483739652510482486858834123369-0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221] + +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.940 units remaining) + [ (Pair 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (remaining gas: 1039993.860 units remaining) + [ 17180093072794558806177035834397932205917577288483739652510482486858834123369 @parameter + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage ] + - location: 8 (remaining gas: 1039993.790 units remaining) + [ 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d @storage + 17180093072794558806177035834397932205917577288483739652510482486858834123369 @parameter ] + - location: 9 (remaining gas: 1039993.380 units remaining) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 10 (remaining gas: 1039993.305 units remaining) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 12 (remaining gas: 1039993.230 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + - location: -1 (remaining gas: 1039993.185 units remaining) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[car.tz-0-(Pair 34 17)-34].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[car.tz-0-(Pair 34 17)-34].out new file mode 100644 index 0000000000000000000000000000000000000000..8386df3eb82f1ae30c62a7b110288f70095a7fd7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[car.tz-0-(Pair 34 17)-34].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[car.tz-0-(Pair 34 17)-34] + +storage + 34 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.920 units remaining) + [ (Pair (Pair 34 17) 0) ] + - location: 9 (remaining gas: 1039993.840 units remaining) + [ (Pair 34 17) @parameter ] + - location: 10 (remaining gas: 1039993.760 units remaining) + [ 34 ] + - location: 11 (remaining gas: 1039993.685 units remaining) + [ {} + 34 ] + - location: 13 (remaining gas: 1039993.610 units remaining) + [ (Pair {} 34) ] + - location: -1 (remaining gas: 1039993.565 units remaining) + [ (Pair {} 34) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cdr.tz-0-(Pair 34 17)-17].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cdr.tz-0-(Pair 34 17)-17].out new file mode 100644 index 0000000000000000000000000000000000000000..1f57049ab02aa71a7ca861daf096347b1a83902a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cdr.tz-0-(Pair 34 17)-17].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[cdr.tz-0-(Pair 34 17)-17] + +storage + 17 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.920 units remaining) + [ (Pair (Pair 34 17) 0) ] + - location: 9 (remaining gas: 1039993.840 units remaining) + [ (Pair 34 17) @parameter ] + - location: 10 (remaining gas: 1039993.760 units remaining) + [ 17 ] + - location: 11 (remaining gas: 1039993.685 units remaining) + [ {} + 17 ] + - location: 13 (remaining gas: 1039993.610 units remaining) + [ (Pair {} 17) ] + - location: -1 (remaining gas: 1039993.565 units remaining) + [ (Pair {} 17) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[chain_id_store.tz-(Some \"NetXdQprcVkpaWU\")-Unit-(Some \".8420090f97.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[chain_id_store.tz-(Some \"NetXdQprcVkpaWU\")-Unit-(Some \".8420090f97.out" new file mode 100644 index 0000000000000000000000000000000000000000..034862a3fde09b5c23fb3a11b3a2923bf395c442 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[chain_id_store.tz-(Some \"NetXdQprcVkpaWU\")-Unit-(Some \".8420090f97.out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[chain_id_store.tz-(Some "NetXdQprcVkpaWU")-Unit-(Some "NetXdQprcVkpaWU")] + +storage + (Some "NetXdQprcVkpaWU") +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039991.950 units remaining) + [ (Pair Unit (Some "NetXdQprcVkpaWU")) ] + - location: 8 (remaining gas: 1039991.875 units remaining) + [ ] + - location: 9 (remaining gas: 1039991.800 units remaining) + [ "NetXdQprcVkpaWU" ] + - location: 10 (remaining gas: 1039991.725 units remaining) + [ (Some "NetXdQprcVkpaWU") ] + - location: 11 (remaining gas: 1039991.650 units remaining) + [ {} + (Some "NetXdQprcVkpaWU") ] + - location: 13 (remaining gas: 1039991.575 units remaining) + [ (Pair {} (Some "NetXdQprcVkpaWU")) ] + - location: -1 (remaining gas: 1039991.530 units remaining) + [ (Pair {} (Some "NetXdQprcVkpaWU")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[chain_id_store.tz-(Some 0x7a06a770)-Unit-(Some \"NetXdQprcVkpaWU\")].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[chain_id_store.tz-(Some 0x7a06a770)-Unit-(Some \"NetXdQprcVkpaWU\")].out" new file mode 100644 index 0000000000000000000000000000000000000000..2b3f6afb4dec8f6477c5fd9fc0e613890701edaf --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[chain_id_store.tz-(Some 0x7a06a770)-Unit-(Some \"NetXdQprcVkpaWU\")].out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[chain_id_store.tz-(Some 0x7a06a770)-Unit-(Some "NetXdQprcVkpaWU")] + +storage + (Some "NetXdQprcVkpaWU") +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.400 units remaining) + [ (Pair Unit (Some "NetXdQprcVkpaWU")) ] + - location: 8 (remaining gas: 1039993.325 units remaining) + [ ] + - location: 9 (remaining gas: 1039993.250 units remaining) + [ "NetXdQprcVkpaWU" ] + - location: 10 (remaining gas: 1039993.175 units remaining) + [ (Some "NetXdQprcVkpaWU") ] + - location: 11 (remaining gas: 1039993.100 units remaining) + [ {} + (Some "NetXdQprcVkpaWU") ] + - location: 13 (remaining gas: 1039993.025 units remaining) + [ (Pair {} (Some "NetXdQprcVkpaWU")) ] + - location: -1 (remaining gas: 1039992.980 units remaining) + [ (Pair {} (Some "NetXdQprcVkpaWU")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[chain_id_store.tz-None-Unit-(Some \"NetXdQprcVkpaWU\")].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[chain_id_store.tz-None-Unit-(Some \"NetXdQprcVkpaWU\")].out" new file mode 100644 index 0000000000000000000000000000000000000000..f1d27bdc7312f6c82857055b5f6219d7d99ddbf3 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[chain_id_store.tz-None-Unit-(Some \"NetXdQprcVkpaWU\")].out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[chain_id_store.tz-None-Unit-(Some "NetXdQprcVkpaWU")] + +storage + (Some "NetXdQprcVkpaWU") +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.690 units remaining) + [ (Pair Unit None) ] + - location: 8 (remaining gas: 1039993.615 units remaining) + [ ] + - location: 9 (remaining gas: 1039993.540 units remaining) + [ "NetXdQprcVkpaWU" ] + - location: 10 (remaining gas: 1039993.465 units remaining) + [ (Some "NetXdQprcVkpaWU") ] + - location: 11 (remaining gas: 1039993.390 units remaining) + [ {} + (Some "NetXdQprcVkpaWU") ] + - location: 13 (remaining gas: 1039993.315 units remaining) + [ (Pair {} (Some "NetXdQprcVkpaWU")) ] + - location: -1 (remaining gas: 1039993.270 units remaining) + [ (Pair {} (Some "NetXdQprcVkpaWU")) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb-get.tz-Unit-(Pair 1 4 2 Unit)-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb-get.tz-Unit-(Pair 1 4 2 Unit)-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..78ba9523b508bcaf92e413dcfbad3a39f55e67a5 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb-get.tz-Unit-(Pair 1 4 2 Unit)-Unit].out @@ -0,0 +1,140 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[comb-get.tz-Unit-(Pair 1 4 2 Unit)-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039941.990 units remaining) + [ (Pair (Pair 1 4 2 Unit) Unit) ] + - location: 11 (remaining gas: 1039941.910 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: 12 (remaining gas: 1039941.830 units remaining) + [ (Pair 1 4 2 Unit) @parameter + (Pair 1 4 2 Unit) @parameter ] + - location: 13 (remaining gas: 1039941.750 units remaining) + [ 1 + (Pair 1 4 2 Unit) @parameter ] + - location: 14 (remaining gas: 1039941.675 units remaining) + [ 1 + 1 + (Pair 1 4 2 Unit) @parameter ] + - location: 19 (remaining gas: 1039941.435 units remaining) + [ 0 + (Pair 1 4 2 Unit) @parameter ] + - location: 20 (remaining gas: 1039941.360 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039941.315 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: 22 (remaining gas: 1039941.215 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039941.170 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: 27 (remaining gas: 1039941.090 units remaining) + [ (Pair 1 4 2 Unit) @parameter + (Pair 1 4 2 Unit) @parameter ] + - location: 28 (remaining gas: 1039940.980 units remaining) + [ 1 + (Pair 1 4 2 Unit) @parameter ] + - location: 30 (remaining gas: 1039940.905 units remaining) + [ 1 + 1 + (Pair 1 4 2 Unit) @parameter ] + - location: 35 (remaining gas: 1039940.665 units remaining) + [ 0 + (Pair 1 4 2 Unit) @parameter ] + - location: 36 (remaining gas: 1039940.590 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039940.545 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: 38 (remaining gas: 1039940.445 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039940.400 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: 43 (remaining gas: 1039940.320 units remaining) + [ (Pair 1 4 2 Unit) @parameter + (Pair 1 4 2 Unit) @parameter ] + - location: 44 (remaining gas: 1039940.209 units remaining) + [ 4 + (Pair 1 4 2 Unit) @parameter ] + - location: 46 (remaining gas: 1039940.134 units remaining) + [ 4 + 4 + (Pair 1 4 2 Unit) @parameter ] + - location: 51 (remaining gas: 1039939.894 units remaining) + [ 0 + (Pair 1 4 2 Unit) @parameter ] + - location: 52 (remaining gas: 1039939.819 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039939.774 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: 54 (remaining gas: 1039939.674 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039939.629 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: 59 (remaining gas: 1039939.549 units remaining) + [ (Pair 1 4 2 Unit) @parameter + (Pair 1 4 2 Unit) @parameter ] + - location: 60 (remaining gas: 1039939.437 units remaining) + [ 2 + (Pair 1 4 2 Unit) @parameter ] + - location: 62 (remaining gas: 1039939.362 units remaining) + [ 2 + 2 + (Pair 1 4 2 Unit) @parameter ] + - location: 67 (remaining gas: 1039939.122 units remaining) + [ 0 + (Pair 1 4 2 Unit) @parameter ] + - location: 68 (remaining gas: 1039939.047 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039939.002 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: 70 (remaining gas: 1039938.902 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039938.857 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: 75 (remaining gas: 1039938.777 units remaining) + [ (Pair 1 4 2 Unit) @parameter + (Pair 1 4 2 Unit) @parameter ] + - location: 76 (remaining gas: 1039938.664 units remaining) + [ Unit + (Pair 1 4 2 Unit) @parameter ] + - location: 78 (remaining gas: 1039938.589 units remaining) + [ Unit + Unit + (Pair 1 4 2 Unit) @parameter ] + - location: 81 (remaining gas: 1039938.489 units remaining) + [ 0 + (Pair 1 4 2 Unit) @parameter ] + - location: 82 (remaining gas: 1039938.414 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039938.369 units remaining) + [ True + (Pair 1 4 2 Unit) @parameter ] + - location: 84 (remaining gas: 1039938.269 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: -1 (remaining gas: 1039938.224 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: 89 (remaining gas: 1039938.149 units remaining) + [ ] + - location: 90 (remaining gas: 1039938.074 units remaining) + [ Unit ] + - location: 91 (remaining gas: 1039937.999 units remaining) + [ {} + Unit ] + - location: 93 (remaining gas: 1039937.924 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039937.879 units remaining) + [ (Pair {} Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb-set-2.tz-None-(Pair 1 4 2 Unit)-(Some (Pair 2 4 \"t.886cc365c6.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb-set-2.tz-None-(Pair 1 4 2 Unit)-(Some (Pair 2 4 \"t.886cc365c6.out" new file mode 100644 index 0000000000000000000000000000000000000000..46903a21a185dc09ae665ff6439d9fb4d2d5d7d9 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb-set-2.tz-None-(Pair 1 4 2 Unit)-(Some (Pair 2 4 \"t.886cc365c6.out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[comb-set-2.tz-None-(Pair 1 4 2 Unit)-(Some (Pair 2 4 "toto" 0x01))] + +storage + (Some (Pair 2 4 "toto" 0x01)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039983.796 units remaining) + [ (Pair (Pair 1 4 2 Unit) None) ] + - location: 16 (remaining gas: 1039983.716 units remaining) + [ (Pair 1 4 2 Unit) @parameter ] + - location: 17 (remaining gas: 1039983.641 units remaining) + [ 2 + (Pair 1 4 2 Unit) @parameter ] + - location: 20 (remaining gas: 1039983.530 units remaining) + [ (Pair 2 4 2 Unit) ] + - location: 22 (remaining gas: 1039983.455 units remaining) + [ "toto" + (Pair 2 4 2 Unit) ] + - location: 25 (remaining gas: 1039983.339 units remaining) + [ (Pair 2 4 "toto" Unit) ] + - location: 27 (remaining gas: 1039983.264 units remaining) + [ 0x01 + (Pair 2 4 "toto" Unit) ] + - location: 30 (remaining gas: 1039983.147 units remaining) + [ (Pair 2 4 "toto" 0x01) ] + - location: 32 (remaining gas: 1039983.072 units remaining) + [ (Some (Pair 2 4 "toto" 0x01)) ] + - location: 33 (remaining gas: 1039982.997 units remaining) + [ {} + (Some (Pair 2 4 "toto" 0x01)) ] + - location: 35 (remaining gas: 1039982.922 units remaining) + [ (Pair {} (Some (Pair 2 4 "toto" 0x01))) ] + - location: -1 (remaining gas: 1039982.877 units remaining) + [ (Pair {} (Some (Pair 2 4 "toto" 0x01))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb-set.tz-(Pair 1 4 2 Unit)-Unit-(Pair 2 12 8 Unit)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb-set.tz-(Pair 1 4 2 Unit)-Unit-(Pair 2 12 8 Unit)].out new file mode 100644 index 0000000000000000000000000000000000000000..ed11ffdcbab6477c01ea649edd98f1a438f132a3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb-set.tz-(Pair 1 4 2 Unit)-Unit-(Pair 2 12 8 Unit)].out @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[comb-set.tz-(Pair 1 4 2 Unit)-Unit-(Pair 2 12 8 Unit)] + +storage + (Pair 2 12 8 Unit) +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039984.270 units remaining) + [ (Pair Unit 1 4 2 Unit) ] + - location: 11 (remaining gas: 1039984.190 units remaining) + [ (Pair 1 4 2 Unit) @storage ] + - location: 12 (remaining gas: 1039984.115 units remaining) + [ 2 + (Pair 1 4 2 Unit) @storage ] + - location: 15 (remaining gas: 1039984.004 units remaining) + [ (Pair 2 4 2 Unit) ] + - location: 17 (remaining gas: 1039983.929 units remaining) + [ 12 + (Pair 2 4 2 Unit) ] + - location: 20 (remaining gas: 1039983.816 units remaining) + [ (Pair 2 12 2 Unit) ] + - location: 22 (remaining gas: 1039983.741 units remaining) + [ 8 + (Pair 2 12 2 Unit) ] + - location: 25 (remaining gas: 1039983.625 units remaining) + [ (Pair 2 12 8 Unit) ] + - location: 27 (remaining gas: 1039983.550 units remaining) + [ Unit + (Pair 2 12 8 Unit) ] + - location: 28 (remaining gas: 1039983.433 units remaining) + [ (Pair 2 12 8 Unit) ] + - location: 30 (remaining gas: 1039983.358 units remaining) + [ {} + (Pair 2 12 8 Unit) ] + - location: 32 (remaining gas: 1039983.283 units remaining) + [ (Pair {} 2 12 8 Unit) ] + - location: -1 (remaining gas: 1039983.238 units remaining) + [ (Pair {} 2 12 8 Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb.tz-(Pair 0 0 0)-Unit-(Pair 1 2 3)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb.tz-(Pair 0 0 0)-Unit-(Pair 1 2 3)].out new file mode 100644 index 0000000000000000000000000000000000000000..ef1a149bb434ac24afc35d0b233845d8da1ab763 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comb.tz-(Pair 0 0 0)-Unit-(Pair 1 2 3)].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[comb.tz-(Pair 0 0 0)-Unit-(Pair 1 2 3)] + +storage + (Pair 1 2 3) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.650 units remaining) + [ (Pair Unit 0 0 0) ] + - location: 10 (remaining gas: 1039989.575 units remaining) + [ ] + - location: 11 (remaining gas: 1039989.500 units remaining) + [ 3 ] + - location: 14 (remaining gas: 1039989.425 units remaining) + [ 2 + 3 ] + - location: 17 (remaining gas: 1039989.350 units remaining) + [ 1 + 2 + 3 ] + - location: 20 (remaining gas: 1039989.275 units remaining) + [ {} + 1 + 2 + 3 ] + - location: 22 (remaining gas: 1039989.152 units remaining) + [ (Pair {} 1 2 3) ] + - location: -1 (remaining gas: 1039989.107 units remaining) + [ (Pair {} 1 2 3) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[compare.tz-Unit-Unit-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[compare.tz-Unit-Unit-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..431b9b9580549cee2d13e1451bfe395f2c6f4b87 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[compare.tz-Unit-Unit-Unit].out @@ -0,0 +1,400 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[compare.tz-Unit-Unit-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039762.979 units remaining) + [ (Pair Unit Unit) ] + - location: 7 (remaining gas: 1039762.904 units remaining) + [ ] + - location: 8 (remaining gas: 1039762.829 units remaining) + [ True ] + - location: 11 (remaining gas: 1039762.749 units remaining) + [ True + True ] + - location: 12 (remaining gas: 1039762.511 units remaining) + [ 0 ] + - location: 14 (remaining gas: 1039762.406 units remaining) + [ True ] + - location: 16 (remaining gas: 1039762.306 units remaining) + [ ] + - location: -1 (remaining gas: 1039762.261 units remaining) + [ ] + - location: 21 (remaining gas: 1039762.186 units remaining) + [ False ] + - location: 24 (remaining gas: 1039762.106 units remaining) + [ False + False ] + - location: 25 (remaining gas: 1039761.868 units remaining) + [ 0 ] + - location: 27 (remaining gas: 1039761.763 units remaining) + [ True ] + - location: 29 (remaining gas: 1039761.663 units remaining) + [ ] + - location: -1 (remaining gas: 1039761.618 units remaining) + [ ] + - location: 34 (remaining gas: 1039761.543 units remaining) + [ False ] + - location: 37 (remaining gas: 1039761.468 units remaining) + [ True + False ] + - location: 40 (remaining gas: 1039761.230 units remaining) + [ 1 ] + - location: 42 (remaining gas: 1039761.125 units remaining) + [ True ] + - location: 44 (remaining gas: 1039761.025 units remaining) + [ ] + - location: -1 (remaining gas: 1039760.980 units remaining) + [ ] + - location: 49 (remaining gas: 1039760.905 units remaining) + [ True ] + - location: 52 (remaining gas: 1039760.830 units remaining) + [ False + True ] + - location: 55 (remaining gas: 1039760.592 units remaining) + [ -1 ] + - location: 57 (remaining gas: 1039760.487 units remaining) + [ True ] + - location: 59 (remaining gas: 1039760.387 units remaining) + [ ] + - location: -1 (remaining gas: 1039760.342 units remaining) + [ ] + - location: 64 (remaining gas: 1039760.267 units remaining) + [ 0xaabbcc ] + - location: 67 (remaining gas: 1039760.187 units remaining) + [ 0xaabbcc + 0xaabbcc ] + - location: 68 (remaining gas: 1039760.037 units remaining) + [ 0 ] + - location: 70 (remaining gas: 1039759.932 units remaining) + [ True ] + - location: 72 (remaining gas: 1039759.832 units remaining) + [ ] + - location: -1 (remaining gas: 1039759.787 units remaining) + [ ] + - location: 77 (remaining gas: 1039759.712 units remaining) + [ 0x ] + - location: 80 (remaining gas: 1039759.637 units remaining) + [ 0x + 0x ] + - location: 83 (remaining gas: 1039759.487 units remaining) + [ 0 ] + - location: 85 (remaining gas: 1039759.382 units remaining) + [ True ] + - location: 87 (remaining gas: 1039759.282 units remaining) + [ ] + - location: -1 (remaining gas: 1039759.237 units remaining) + [ ] + - location: 92 (remaining gas: 1039759.162 units remaining) + [ 0x ] + - location: 95 (remaining gas: 1039759.087 units remaining) + [ 0x01 + 0x ] + - location: 98 (remaining gas: 1039758.937 units remaining) + [ 1 ] + - location: 100 (remaining gas: 1039758.832 units remaining) + [ True ] + - location: 102 (remaining gas: 1039758.732 units remaining) + [ ] + - location: -1 (remaining gas: 1039758.687 units remaining) + [ ] + - location: 107 (remaining gas: 1039758.612 units remaining) + [ 0x01 ] + - location: 110 (remaining gas: 1039758.537 units remaining) + [ 0x02 + 0x01 ] + - location: 113 (remaining gas: 1039758.387 units remaining) + [ 1 ] + - location: 115 (remaining gas: 1039758.282 units remaining) + [ True ] + - location: 117 (remaining gas: 1039758.182 units remaining) + [ ] + - location: -1 (remaining gas: 1039758.137 units remaining) + [ ] + - location: 122 (remaining gas: 1039758.062 units remaining) + [ 0x02 ] + - location: 125 (remaining gas: 1039757.987 units remaining) + [ 0x01 + 0x02 ] + - location: 128 (remaining gas: 1039757.837 units remaining) + [ -1 ] + - location: 130 (remaining gas: 1039757.732 units remaining) + [ True ] + - location: 132 (remaining gas: 1039757.632 units remaining) + [ ] + - location: -1 (remaining gas: 1039757.587 units remaining) + [ ] + - location: 137 (remaining gas: 1039757.512 units remaining) + [ 1 ] + - location: 140 (remaining gas: 1039757.432 units remaining) + [ 1 + 1 ] + - location: 141 (remaining gas: 1039757.252 units remaining) + [ 0 ] + - location: 143 (remaining gas: 1039757.147 units remaining) + [ True ] + - location: 145 (remaining gas: 1039757.047 units remaining) + [ ] + - location: -1 (remaining gas: 1039757.002 units remaining) + [ ] + - location: 150 (remaining gas: 1039756.927 units remaining) + [ 10 ] + - location: 153 (remaining gas: 1039756.852 units remaining) + [ 5 + 10 ] + - location: 156 (remaining gas: 1039756.672 units remaining) + [ -1 ] + - location: 158 (remaining gas: 1039756.567 units remaining) + [ True ] + - location: 160 (remaining gas: 1039756.467 units remaining) + [ ] + - location: -1 (remaining gas: 1039756.422 units remaining) + [ ] + - location: 165 (remaining gas: 1039756.347 units remaining) + [ -4 ] + - location: 168 (remaining gas: 1039756.272 units remaining) + [ 1923 + -4 ] + - location: 171 (remaining gas: 1039756.092 units remaining) + [ 1 ] + - location: 173 (remaining gas: 1039755.987 units remaining) + [ True ] + - location: 175 (remaining gas: 1039755.887 units remaining) + [ ] + - location: -1 (remaining gas: 1039755.842 units remaining) + [ ] + - location: 180 (remaining gas: 1039755.767 units remaining) + [ 1 ] + - location: 183 (remaining gas: 1039755.687 units remaining) + [ 1 + 1 ] + - location: 184 (remaining gas: 1039755.507 units remaining) + [ 0 ] + - location: 186 (remaining gas: 1039755.402 units remaining) + [ True ] + - location: 188 (remaining gas: 1039755.302 units remaining) + [ ] + - location: -1 (remaining gas: 1039755.257 units remaining) + [ ] + - location: 193 (remaining gas: 1039755.182 units remaining) + [ 10 ] + - location: 196 (remaining gas: 1039755.107 units remaining) + [ 5 + 10 ] + - location: 199 (remaining gas: 1039754.927 units remaining) + [ -1 ] + - location: 201 (remaining gas: 1039754.822 units remaining) + [ True ] + - location: 203 (remaining gas: 1039754.722 units remaining) + [ ] + - location: -1 (remaining gas: 1039754.677 units remaining) + [ ] + - location: 208 (remaining gas: 1039754.602 units remaining) + [ 4 ] + - location: 211 (remaining gas: 1039754.527 units remaining) + [ 1923 + 4 ] + - location: 214 (remaining gas: 1039754.347 units remaining) + [ 1 ] + - location: 216 (remaining gas: 1039754.242 units remaining) + [ True ] + - location: 218 (remaining gas: 1039754.142 units remaining) + [ ] + - location: -1 (remaining gas: 1039754.097 units remaining) + [ ] + - location: 223 (remaining gas: 1039754.022 units remaining) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 226 (remaining gas: 1039753.942 units remaining) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 227 (remaining gas: 1039753.702 units remaining) + [ 0 ] + - location: 229 (remaining gas: 1039753.597 units remaining) + [ True ] + - location: 231 (remaining gas: 1039753.497 units remaining) + [ ] + - location: -1 (remaining gas: 1039753.452 units remaining) + [ ] + - location: 236 (remaining gas: 1039753.377 units remaining) + [ "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" ] + - location: 239 (remaining gas: 1039753.302 units remaining) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" ] + - location: 242 (remaining gas: 1039753.062 units remaining) + [ -1 ] + - location: 244 (remaining gas: 1039752.957 units remaining) + [ True ] + - location: 246 (remaining gas: 1039752.857 units remaining) + [ ] + - location: -1 (remaining gas: 1039752.812 units remaining) + [ ] + - location: 251 (remaining gas: 1039752.737 units remaining) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 254 (remaining gas: 1039752.662 units remaining) + [ "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" + "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 257 (remaining gas: 1039752.422 units remaining) + [ 1 ] + - location: 259 (remaining gas: 1039752.317 units remaining) + [ True ] + - location: 261 (remaining gas: 1039752.217 units remaining) + [ ] + - location: -1 (remaining gas: 1039752.172 units remaining) + [ ] + - location: 266 (remaining gas: 1039752.097 units remaining) + [ 1 ] + - location: 269 (remaining gas: 1039752.017 units remaining) + [ 1 + 1 ] + - location: 270 (remaining gas: 1039751.883 units remaining) + [ 0 ] + - location: 272 (remaining gas: 1039751.778 units remaining) + [ True ] + - location: 274 (remaining gas: 1039751.678 units remaining) + [ ] + - location: -1 (remaining gas: 1039751.633 units remaining) + [ ] + - location: 279 (remaining gas: 1039751.558 units remaining) + [ 10 ] + - location: 282 (remaining gas: 1039751.483 units remaining) + [ 5 + 10 ] + - location: 285 (remaining gas: 1039751.349 units remaining) + [ -1 ] + - location: 287 (remaining gas: 1039751.244 units remaining) + [ True ] + - location: 289 (remaining gas: 1039751.144 units remaining) + [ ] + - location: -1 (remaining gas: 1039751.099 units remaining) + [ ] + - location: 294 (remaining gas: 1039751.024 units remaining) + [ 4 ] + - location: 297 (remaining gas: 1039750.949 units remaining) + [ 1923 + 4 ] + - location: 300 (remaining gas: 1039750.815 units remaining) + [ 1 ] + - location: 302 (remaining gas: 1039750.710 units remaining) + [ True ] + - location: 304 (remaining gas: 1039750.610 units remaining) + [ ] + - location: -1 (remaining gas: 1039750.565 units remaining) + [ ] + - location: 309 (remaining gas: 1039750.490 units remaining) + [ "AABBCC" ] + - location: 312 (remaining gas: 1039750.410 units remaining) + [ "AABBCC" + "AABBCC" ] + - location: 313 (remaining gas: 1039750.260 units remaining) + [ 0 ] + - location: 315 (remaining gas: 1039750.155 units remaining) + [ True ] + - location: 317 (remaining gas: 1039750.055 units remaining) + [ ] + - location: -1 (remaining gas: 1039750.010 units remaining) + [ ] + - location: 322 (remaining gas: 1039749.935 units remaining) + [ "" ] + - location: 325 (remaining gas: 1039749.860 units remaining) + [ "" + "" ] + - location: 328 (remaining gas: 1039749.710 units remaining) + [ 0 ] + - location: 330 (remaining gas: 1039749.605 units remaining) + [ True ] + - location: 332 (remaining gas: 1039749.505 units remaining) + [ ] + - location: -1 (remaining gas: 1039749.460 units remaining) + [ ] + - location: 337 (remaining gas: 1039749.385 units remaining) + [ "" ] + - location: 340 (remaining gas: 1039749.310 units remaining) + [ "a" + "" ] + - location: 343 (remaining gas: 1039749.160 units remaining) + [ 1 ] + - location: 345 (remaining gas: 1039749.055 units remaining) + [ True ] + - location: 347 (remaining gas: 1039748.955 units remaining) + [ ] + - location: -1 (remaining gas: 1039748.910 units remaining) + [ ] + - location: 352 (remaining gas: 1039748.835 units remaining) + [ "a" ] + - location: 355 (remaining gas: 1039748.760 units remaining) + [ "b" + "a" ] + - location: 358 (remaining gas: 1039748.610 units remaining) + [ 1 ] + - location: 360 (remaining gas: 1039748.505 units remaining) + [ True ] + - location: 362 (remaining gas: 1039748.405 units remaining) + [ ] + - location: -1 (remaining gas: 1039748.360 units remaining) + [ ] + - location: 367 (remaining gas: 1039748.285 units remaining) + [ "b" ] + - location: 370 (remaining gas: 1039748.210 units remaining) + [ "a" + "b" ] + - location: 373 (remaining gas: 1039748.060 units remaining) + [ -1 ] + - location: 375 (remaining gas: 1039747.955 units remaining) + [ True ] + - location: 377 (remaining gas: 1039747.855 units remaining) + [ ] + - location: -1 (remaining gas: 1039747.810 units remaining) + [ ] + - location: 382 (remaining gas: 1039747.735 units remaining) + [ "2019-09-16T08:38:05Z" ] + - location: 385 (remaining gas: 1039747.655 units remaining) + [ "2019-09-16T08:38:05Z" + "2019-09-16T08:38:05Z" ] + - location: 386 (remaining gas: 1039747.485 units remaining) + [ 0 ] + - location: 388 (remaining gas: 1039747.380 units remaining) + [ True ] + - location: 390 (remaining gas: 1039747.280 units remaining) + [ ] + - location: -1 (remaining gas: 1039747.235 units remaining) + [ ] + - location: 395 (remaining gas: 1039747.160 units remaining) + [ "2017-09-16T08:38:04Z" ] + - location: 398 (remaining gas: 1039747.085 units remaining) + [ "2019-09-16T08:38:05Z" + "2017-09-16T08:38:04Z" ] + - location: 401 (remaining gas: 1039746.915 units remaining) + [ 1 ] + - location: 403 (remaining gas: 1039746.810 units remaining) + [ True ] + - location: 405 (remaining gas: 1039746.710 units remaining) + [ ] + - location: -1 (remaining gas: 1039746.665 units remaining) + [ ] + - location: 410 (remaining gas: 1039746.590 units remaining) + [ "2019-09-16T08:38:05Z" ] + - location: 413 (remaining gas: 1039746.515 units remaining) + [ "2019-09-16T08:38:04Z" + "2019-09-16T08:38:05Z" ] + - location: 416 (remaining gas: 1039746.345 units remaining) + [ -1 ] + - location: 418 (remaining gas: 1039746.240 units remaining) + [ True ] + - location: 420 (remaining gas: 1039746.140 units remaining) + [ ] + - location: -1 (remaining gas: 1039746.095 units remaining) + [ ] + - location: 425 (remaining gas: 1039746.020 units remaining) + [ Unit ] + - location: 426 (remaining gas: 1039745.945 units remaining) + [ {} + Unit ] + - location: 428 (remaining gas: 1039745.870 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039745.825 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comparisons.tz-{}-{ -9999999; -1 ; 0 ; 1 ; 9999999 }-{ .bbaa8924d2.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comparisons.tz-{}-{ -9999999; -1 ; 0 ; 1 ; 9999999 }-{ .bbaa8924d2.out new file mode 100644 index 0000000000000000000000000000000000000000..36957f35955d61aed2747d2486aaba92ecee9025 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[comparisons.tz-{}-{ -9999999; -1 ; 0 ; 1 ; 9999999 }-{ .bbaa8924d2.out @@ -0,0 +1,363 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[comparisons.tz-{}-{ -9999999; -1 ; 0 ; 1 ; 9999999 }-{ { False ; False ; False ; True ; True } ;\n { False ; False ; True ; True ; True } ;\n { True ; True ; False ; False ; False } ;\n { True ; True ; True ; False ; False } ;\n { True ; True ; False ; True ; True } ;\n { False ; False ; True ; False ; False } }] + +storage + { { False ; False ; False ; True ; True } ; + { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039960.920 units remaining) + [ (Pair { -9999999 ; -1 ; 0 ; 1 ; 9999999 } {}) ] + - location: 10 (remaining gas: 1039960.840 units remaining) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 11 (remaining gas: 1039960.765 units remaining) + [ {} + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 16 (remaining gas: 1039960.610 units remaining) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 19 (remaining gas: 1039959.945 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 18 (remaining gas: 1039959.900 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 19 (remaining gas: 1039959.825 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 18 (remaining gas: 1039959.780 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 19 (remaining gas: 1039959.705 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 18 (remaining gas: 1039959.660 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 19 (remaining gas: 1039959.585 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 18 (remaining gas: 1039959.540 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 19 (remaining gas: 1039959.465 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 18 (remaining gas: 1039959.420 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 17 (remaining gas: 1039959.420 units remaining) + [ { False ; False ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: -1 (remaining gas: 1039959.375 units remaining) + [ { False ; False ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 14 (remaining gas: 1039959.375 units remaining) + [ {} + { False ; False ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 20 (remaining gas: 1039959.305 units remaining) + [ { False ; False ; True ; False ; False } + {} + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 21 (remaining gas: 1039959.225 units remaining) + [ { { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 24 (remaining gas: 1039959.070 units remaining) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 27 (remaining gas: 1039958.405 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 26 (remaining gas: 1039958.360 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 27 (remaining gas: 1039958.285 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 26 (remaining gas: 1039958.240 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 27 (remaining gas: 1039958.165 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 26 (remaining gas: 1039958.120 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 27 (remaining gas: 1039958.045 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 26 (remaining gas: 1039958 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 27 (remaining gas: 1039957.925 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 26 (remaining gas: 1039957.880 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 25 (remaining gas: 1039957.880 units remaining) + [ { True ; True ; False ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: -1 (remaining gas: 1039957.835 units remaining) + [ { True ; True ; False ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 22 (remaining gas: 1039957.835 units remaining) + [ { { False ; False ; True ; False ; False } } + { True ; True ; False ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 28 (remaining gas: 1039957.765 units remaining) + [ { True ; True ; False ; True ; True } + { { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 29 (remaining gas: 1039957.685 units remaining) + [ { { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 32 (remaining gas: 1039957.530 units remaining) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 35 (remaining gas: 1039956.865 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 34 (remaining gas: 1039956.820 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 35 (remaining gas: 1039956.745 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 34 (remaining gas: 1039956.700 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 35 (remaining gas: 1039956.625 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 34 (remaining gas: 1039956.580 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 35 (remaining gas: 1039956.505 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 34 (remaining gas: 1039956.460 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 35 (remaining gas: 1039956.385 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 34 (remaining gas: 1039956.340 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 33 (remaining gas: 1039956.340 units remaining) + [ { True ; True ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: -1 (remaining gas: 1039956.295 units remaining) + [ { True ; True ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 30 (remaining gas: 1039956.295 units remaining) + [ { { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { True ; True ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 36 (remaining gas: 1039956.225 units remaining) + [ { True ; True ; True ; False ; False } + { { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 37 (remaining gas: 1039956.145 units remaining) + [ { { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 40 (remaining gas: 1039955.990 units remaining) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 43 (remaining gas: 1039955.325 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 42 (remaining gas: 1039955.280 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 43 (remaining gas: 1039955.205 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 42 (remaining gas: 1039955.160 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 43 (remaining gas: 1039955.085 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 42 (remaining gas: 1039955.040 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 43 (remaining gas: 1039954.965 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 42 (remaining gas: 1039954.920 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 43 (remaining gas: 1039954.845 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 42 (remaining gas: 1039954.800 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 41 (remaining gas: 1039954.800 units remaining) + [ { True ; True ; False ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: -1 (remaining gas: 1039954.755 units remaining) + [ { True ; True ; False ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 38 (remaining gas: 1039954.755 units remaining) + [ { { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { True ; True ; False ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 44 (remaining gas: 1039954.685 units remaining) + [ { True ; True ; False ; False ; False } + { { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 45 (remaining gas: 1039954.605 units remaining) + [ { { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 48 (remaining gas: 1039954.450 units remaining) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 51 (remaining gas: 1039953.785 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 50 (remaining gas: 1039953.740 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 51 (remaining gas: 1039953.665 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 50 (remaining gas: 1039953.620 units remaining) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 51 (remaining gas: 1039953.545 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 50 (remaining gas: 1039953.500 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 51 (remaining gas: 1039953.425 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 50 (remaining gas: 1039953.380 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 51 (remaining gas: 1039953.305 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 50 (remaining gas: 1039953.260 units remaining) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 49 (remaining gas: 1039953.260 units remaining) + [ { False ; False ; True ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: -1 (remaining gas: 1039953.215 units remaining) + [ { False ; False ; True ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 46 (remaining gas: 1039953.215 units remaining) + [ { { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { False ; False ; True ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 52 (remaining gas: 1039953.145 units remaining) + [ { False ; False ; True ; True ; True } + { { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 53 (remaining gas: 1039953.065 units remaining) + [ { { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } @parameter ] + - location: 58 (remaining gas: 1039952.325 units remaining) + [ False ] + - location: 57 (remaining gas: 1039952.280 units remaining) + [ False ] + - location: 58 (remaining gas: 1039952.205 units remaining) + [ False ] + - location: 57 (remaining gas: 1039952.160 units remaining) + [ False ] + - location: 58 (remaining gas: 1039952.085 units remaining) + [ False ] + - location: 57 (remaining gas: 1039952.040 units remaining) + [ False ] + - location: 58 (remaining gas: 1039951.965 units remaining) + [ True ] + - location: 57 (remaining gas: 1039951.920 units remaining) + [ True ] + - location: 58 (remaining gas: 1039951.845 units remaining) + [ True ] + - location: 57 (remaining gas: 1039951.800 units remaining) + [ True ] + - location: 56 (remaining gas: 1039951.800 units remaining) + [ { False ; False ; False ; True ; True } ] + - location: 55 (remaining gas: 1039951.755 units remaining) + [ { False ; False ; False ; True ; True } ] + - location: 54 (remaining gas: 1039951.755 units remaining) + [ { { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { False ; False ; False ; True ; True } ] + - location: 59 (remaining gas: 1039951.685 units remaining) + [ { False ; False ; False ; True ; True } + { { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } ] + - location: 60 (remaining gas: 1039951.605 units remaining) + [ { { False ; False ; False ; True ; True } ; + { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } ] + - location: 61 (remaining gas: 1039951.530 units remaining) + [ {} + { { False ; False ; False ; True ; True } ; + { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } ] + - location: 63 (remaining gas: 1039951.455 units remaining) + [ (Pair {} + { { False ; False ; False ; True ; True } ; + { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } }) ] + - location: -1 (remaining gas: 1039951.410 units remaining) + [ (Pair {} + { { False ; False ; False ; True ; True } ; + { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{ \"World!\" }-{ \"Hello World!\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{ \"World!\" }-{ \"Hello World!\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..91ce8cc50748f26897691c1853407612dfdb1a81 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{ \"World!\" }-{ \"Hello World!\" }].out" @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{ "World!" }-{ "Hello World!" }] + +storage + { "Hello World!" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039991.972 units remaining) + [ (Pair { "World!" } {}) ] + - location: 9 (remaining gas: 1039991.892 units remaining) + [ { "World!" } @parameter ] + - location: 12 (remaining gas: 1039991.275 units remaining) + [ "Hello " @hello + "World!" @parameter.elt ] + - location: 15 (remaining gas: 1039991.165 units remaining) + [ "Hello World!" ] + - location: -1 (remaining gas: 1039991.120 units remaining) + [ "Hello World!" ] + - location: 10 (remaining gas: 1039991.120 units remaining) + [ { "Hello World!" } ] + - location: 16 (remaining gas: 1039991.045 units remaining) + [ {} + { "Hello World!" } ] + - location: 18 (remaining gas: 1039990.970 units remaining) + [ (Pair {} { "Hello World!" }) ] + - location: -1 (remaining gas: 1039990.925 units remaining) + [ (Pair {} { "Hello World!" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{ \"test1\" ; \"test2\" }-{ \"Hello test1.c27e8c3ee6.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{ \"test1\" ; \"test2\" }-{ \"Hello test1.c27e8c3ee6.out" new file mode 100644 index 0000000000000000000000000000000000000000..728c01a6e2e2417afaad0feca6b2b8783a0301a6 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{ \"test1\" ; \"test2\" }-{ \"Hello test1.c27e8c3ee6.out" @@ -0,0 +1,37 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{ "test1" ; "test2" }-{ "Hello test1" ; "Hello test2" }] + +storage + { "Hello test1" ; "Hello test2" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039991.678 units remaining) + [ (Pair { "test1" ; "test2" } {}) ] + - location: 9 (remaining gas: 1039991.598 units remaining) + [ { "test1" ; "test2" } @parameter ] + - location: 12 (remaining gas: 1039990.969 units remaining) + [ "Hello " @hello + "test1" @parameter.elt ] + - location: 15 (remaining gas: 1039990.859 units remaining) + [ "Hello test1" ] + - location: -1 (remaining gas: 1039990.814 units remaining) + [ "Hello test1" ] + - location: 12 (remaining gas: 1039990.739 units remaining) + [ "Hello " @hello + "test2" @parameter.elt ] + - location: 15 (remaining gas: 1039990.629 units remaining) + [ "Hello test2" ] + - location: -1 (remaining gas: 1039990.584 units remaining) + [ "Hello test2" ] + - location: 10 (remaining gas: 1039990.584 units remaining) + [ { "Hello test1" ; "Hello test2" } ] + - location: 16 (remaining gas: 1039990.509 units remaining) + [ {} + { "Hello test1" ; "Hello test2" } ] + - location: 18 (remaining gas: 1039990.434 units remaining) + [ (Pair {} { "Hello test1" ; "Hello test2" }) ] + - location: -1 (remaining gas: 1039990.389 units remaining) + [ (Pair {} { "Hello test1" ; "Hello test2" }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{}-{}].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{}-{}].out new file mode 100644 index 0000000000000000000000000000000000000000..abf0bb01d1df79ebac832d4e7eb9c92b1414e976 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{}-{}].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[concat_hello.tz-{}-{}-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.286 units remaining) + [ (Pair {} {}) ] + - location: 9 (remaining gas: 1039992.206 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039991.676 units remaining) + [ {} ] + - location: 16 (remaining gas: 1039991.601 units remaining) + [ {} + {} ] + - location: 18 (remaining gas: 1039991.526 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039991.481 units remaining) + [ (Pair {} {}) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{ 0xab ; 0xcd }-{ 0xffab ; 0xffcd }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{ 0xab ; 0xcd }-{ 0xffab ; 0xffcd }].out new file mode 100644 index 0000000000000000000000000000000000000000..8b118a0b35430991460512f535854a4c53a4dcc2 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{ 0xab ; 0xcd }-{ 0xffab ; 0xffcd }].out @@ -0,0 +1,37 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{ 0xab ; 0xcd }-{ 0xffab ; 0xffcd }] + +storage + { 0xffab ; 0xffcd } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039991.880 units remaining) + [ (Pair { 0xab ; 0xcd } {}) ] + - location: 9 (remaining gas: 1039991.800 units remaining) + [ { 0xab ; 0xcd } @parameter ] + - location: 12 (remaining gas: 1039991.171 units remaining) + [ 0xff + 0xab @parameter.elt ] + - location: 15 (remaining gas: 1039991.061 units remaining) + [ 0xffab ] + - location: -1 (remaining gas: 1039991.016 units remaining) + [ 0xffab ] + - location: 12 (remaining gas: 1039990.941 units remaining) + [ 0xff + 0xcd @parameter.elt ] + - location: 15 (remaining gas: 1039990.831 units remaining) + [ 0xffcd ] + - location: -1 (remaining gas: 1039990.786 units remaining) + [ 0xffcd ] + - location: 10 (remaining gas: 1039990.786 units remaining) + [ { 0xffab ; 0xffcd } ] + - location: 16 (remaining gas: 1039990.711 units remaining) + [ {} + { 0xffab ; 0xffcd } ] + - location: 18 (remaining gas: 1039990.636 units remaining) + [ (Pair {} { 0xffab ; 0xffcd }) ] + - location: -1 (remaining gas: 1039990.591 units remaining) + [ (Pair {} { 0xffab ; 0xffcd }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{ 0xcd }-{ 0xffcd }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{ 0xcd }-{ 0xffcd }].out new file mode 100644 index 0000000000000000000000000000000000000000..9df77d5cd22fe866538748f823f057c474cc049f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{ 0xcd }-{ 0xffcd }].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{ 0xcd }-{ 0xffcd }] + +storage + { 0xffcd } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.120 units remaining) + [ (Pair { 0xcd } {}) ] + - location: 9 (remaining gas: 1039992.040 units remaining) + [ { 0xcd } @parameter ] + - location: 12 (remaining gas: 1039991.423 units remaining) + [ 0xff + 0xcd @parameter.elt ] + - location: 15 (remaining gas: 1039991.313 units remaining) + [ 0xffcd ] + - location: -1 (remaining gas: 1039991.268 units remaining) + [ 0xffcd ] + - location: 10 (remaining gas: 1039991.268 units remaining) + [ { 0xffcd } ] + - location: 16 (remaining gas: 1039991.193 units remaining) + [ {} + { 0xffcd } ] + - location: 18 (remaining gas: 1039991.118 units remaining) + [ (Pair {} { 0xffcd }) ] + - location: -1 (remaining gas: 1039991.073 units remaining) + [ (Pair {} { 0xffcd }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{}-{}].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{}-{}].out new file mode 100644 index 0000000000000000000000000000000000000000..56a596308daf5980108e872c7b8b2967e77db571 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{}-{}].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[concat_hello_bytes.tz-{}-{}-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.360 units remaining) + [ (Pair {} {}) ] + - location: 9 (remaining gas: 1039992.280 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039991.750 units remaining) + [ {} ] + - location: 16 (remaining gas: 1039991.675 units remaining) + [ {} + {} ] + - location: 18 (remaining gas: 1039991.600 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039991.555 units remaining) + [ (Pair {} {}) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_list.tz-\"\"-{ \"Hello\" ; \" \" ; \"World\" ; \"!\" }-\"He.0c7b4cd53c.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_list.tz-\"\"-{ \"Hello\" ; \" \" ; \"World\" ; \"!\" }-\"He.0c7b4cd53c.out" new file mode 100644 index 0000000000000000000000000000000000000000..bfb78640b083f2966719bc6e9e94c18a4730f0ea --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_list.tz-\"\"-{ \"Hello\" ; \" \" ; \"World\" ; \"!\" }-\"He.0c7b4cd53c.out" @@ -0,0 +1,117 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[concat_list.tz-""-{ "Hello" ; " " ; "World" ; "!" }-"Hello World!"] + +storage + "Hello World!" +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039985.686 units remaining) + [ (Pair { "Hello" ; " " ; "World" ; "!" } "") ] + - location: 8 (remaining gas: 1039985.606 units remaining) + [ { "Hello" ; " " ; "World" ; "!" } @parameter ] + - location: 9 (remaining gas: 1039985.531 units remaining) + [ "" + { "Hello" ; " " ; "World" ; "!" } @parameter ] + - location: 12 (remaining gas: 1039985.461 units remaining) + [ { "Hello" ; " " ; "World" ; "!" } @parameter + "" ] + - location: 15 (remaining gas: 1039984.833 units remaining) + [ "" + "Hello" @parameter.elt ] + - location: 18 (remaining gas: 1039984.683 units remaining) + [ {} + "Hello" @parameter.elt ] + - location: 20 (remaining gas: 1039984.613 units remaining) + [ "Hello" @parameter.elt + {} ] + - location: 21 (remaining gas: 1039984.533 units remaining) + [ { "Hello" } ] + - location: -1 (remaining gas: 1039984.488 units remaining) + [ { "Hello" } ] + - location: 16 (remaining gas: 1039984.488 units remaining) + [ "" + { "Hello" } ] + - location: 22 (remaining gas: 1039984.408 units remaining) + [ { "" ; "Hello" } ] + - location: 23 (remaining gas: 1039984.258 units remaining) + [ "Hello" ] + - location: -1 (remaining gas: 1039984.213 units remaining) + [ "Hello" ] + - location: 15 (remaining gas: 1039984.143 units remaining) + [ "Hello" + " " @parameter.elt ] + - location: 18 (remaining gas: 1039983.993 units remaining) + [ {} + " " @parameter.elt ] + - location: 20 (remaining gas: 1039983.923 units remaining) + [ " " @parameter.elt + {} ] + - location: 21 (remaining gas: 1039983.843 units remaining) + [ { " " } ] + - location: -1 (remaining gas: 1039983.798 units remaining) + [ { " " } ] + - location: 16 (remaining gas: 1039983.798 units remaining) + [ "Hello" + { " " } ] + - location: 22 (remaining gas: 1039983.718 units remaining) + [ { "Hello" ; " " } ] + - location: 23 (remaining gas: 1039983.568 units remaining) + [ "Hello " ] + - location: -1 (remaining gas: 1039983.523 units remaining) + [ "Hello " ] + - location: 15 (remaining gas: 1039983.453 units remaining) + [ "Hello " + "World" @parameter.elt ] + - location: 18 (remaining gas: 1039983.303 units remaining) + [ {} + "World" @parameter.elt ] + - location: 20 (remaining gas: 1039983.233 units remaining) + [ "World" @parameter.elt + {} ] + - location: 21 (remaining gas: 1039983.153 units remaining) + [ { "World" } ] + - location: -1 (remaining gas: 1039983.108 units remaining) + [ { "World" } ] + - location: 16 (remaining gas: 1039983.108 units remaining) + [ "Hello " + { "World" } ] + - location: 22 (remaining gas: 1039983.028 units remaining) + [ { "Hello " ; "World" } ] + - location: 23 (remaining gas: 1039982.877 units remaining) + [ "Hello World" ] + - location: -1 (remaining gas: 1039982.832 units remaining) + [ "Hello World" ] + - location: 15 (remaining gas: 1039982.762 units remaining) + [ "Hello World" + "!" @parameter.elt ] + - location: 18 (remaining gas: 1039982.612 units remaining) + [ {} + "!" @parameter.elt ] + - location: 20 (remaining gas: 1039982.542 units remaining) + [ "!" @parameter.elt + {} ] + - location: 21 (remaining gas: 1039982.462 units remaining) + [ { "!" } ] + - location: -1 (remaining gas: 1039982.417 units remaining) + [ { "!" } ] + - location: 16 (remaining gas: 1039982.417 units remaining) + [ "Hello World" + { "!" } ] + - location: 22 (remaining gas: 1039982.337 units remaining) + [ { "Hello World" ; "!" } ] + - location: 23 (remaining gas: 1039982.186 units remaining) + [ "Hello World!" ] + - location: -1 (remaining gas: 1039982.141 units remaining) + [ "Hello World!" ] + - location: 13 (remaining gas: 1039982.141 units remaining) + [ "Hello World!" ] + - location: 24 (remaining gas: 1039982.066 units remaining) + [ {} + "Hello World!" ] + - location: 26 (remaining gas: 1039981.991 units remaining) + [ (Pair {} "Hello World!") ] + - location: -1 (remaining gas: 1039981.946 units remaining) + [ (Pair {} "Hello World!") ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_list.tz-\"\"-{ \"a\" ; \"b\" ; \"c\" }-\"abc\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_list.tz-\"\"-{ \"a\" ; \"b\" ; \"c\" }-\"abc\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..8184322ccc3be6b00176897c8a4a81bc4be8e8a3 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_list.tz-\"\"-{ \"a\" ; \"b\" ; \"c\" }-\"abc\"].out" @@ -0,0 +1,95 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[concat_list.tz-""-{ "a" ; "b" ; "c" }-"abc"] + +storage + "abc" +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039986.030 units remaining) + [ (Pair { "a" ; "b" ; "c" } "") ] + - location: 8 (remaining gas: 1039985.950 units remaining) + [ { "a" ; "b" ; "c" } @parameter ] + - location: 9 (remaining gas: 1039985.875 units remaining) + [ "" + { "a" ; "b" ; "c" } @parameter ] + - location: 12 (remaining gas: 1039985.805 units remaining) + [ { "a" ; "b" ; "c" } @parameter + "" ] + - location: 15 (remaining gas: 1039985.184 units remaining) + [ "" + "a" @parameter.elt ] + - location: 18 (remaining gas: 1039985.034 units remaining) + [ {} + "a" @parameter.elt ] + - location: 20 (remaining gas: 1039984.964 units remaining) + [ "a" @parameter.elt + {} ] + - location: 21 (remaining gas: 1039984.884 units remaining) + [ { "a" } ] + - location: -1 (remaining gas: 1039984.839 units remaining) + [ { "a" } ] + - location: 16 (remaining gas: 1039984.839 units remaining) + [ "" + { "a" } ] + - location: 22 (remaining gas: 1039984.759 units remaining) + [ { "" ; "a" } ] + - location: 23 (remaining gas: 1039984.609 units remaining) + [ "a" ] + - location: -1 (remaining gas: 1039984.564 units remaining) + [ "a" ] + - location: 15 (remaining gas: 1039984.494 units remaining) + [ "a" + "b" @parameter.elt ] + - location: 18 (remaining gas: 1039984.344 units remaining) + [ {} + "b" @parameter.elt ] + - location: 20 (remaining gas: 1039984.274 units remaining) + [ "b" @parameter.elt + {} ] + - location: 21 (remaining gas: 1039984.194 units remaining) + [ { "b" } ] + - location: -1 (remaining gas: 1039984.149 units remaining) + [ { "b" } ] + - location: 16 (remaining gas: 1039984.149 units remaining) + [ "a" + { "b" } ] + - location: 22 (remaining gas: 1039984.069 units remaining) + [ { "a" ; "b" } ] + - location: 23 (remaining gas: 1039983.919 units remaining) + [ "ab" ] + - location: -1 (remaining gas: 1039983.874 units remaining) + [ "ab" ] + - location: 15 (remaining gas: 1039983.804 units remaining) + [ "ab" + "c" @parameter.elt ] + - location: 18 (remaining gas: 1039983.654 units remaining) + [ {} + "c" @parameter.elt ] + - location: 20 (remaining gas: 1039983.584 units remaining) + [ "c" @parameter.elt + {} ] + - location: 21 (remaining gas: 1039983.504 units remaining) + [ { "c" } ] + - location: -1 (remaining gas: 1039983.459 units remaining) + [ { "c" } ] + - location: 16 (remaining gas: 1039983.459 units remaining) + [ "ab" + { "c" } ] + - location: 22 (remaining gas: 1039983.379 units remaining) + [ { "ab" ; "c" } ] + - location: 23 (remaining gas: 1039983.229 units remaining) + [ "abc" ] + - location: -1 (remaining gas: 1039983.184 units remaining) + [ "abc" ] + - location: 13 (remaining gas: 1039983.184 units remaining) + [ "abc" ] + - location: 24 (remaining gas: 1039983.109 units remaining) + [ {} + "abc" ] + - location: 26 (remaining gas: 1039983.034 units remaining) + [ (Pair {} "abc") ] + - location: -1 (remaining gas: 1039982.989 units remaining) + [ (Pair {} "abc") ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_list.tz-\"\"-{}-\"\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_list.tz-\"\"-{}-\"\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..d3b7104d5f045e126bbc6c97c15ceb30fce5a67a --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[concat_list.tz-\"\"-{}-\"\"].out" @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[concat_list.tz-""-{}-""] + +storage + "" +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039986.822 units remaining) + [ (Pair {} "") ] + - location: 8 (remaining gas: 1039986.742 units remaining) + [ {} @parameter ] + - location: 9 (remaining gas: 1039986.667 units remaining) + [ "" + {} @parameter ] + - location: 12 (remaining gas: 1039986.597 units remaining) + [ {} @parameter + "" ] + - location: 13 (remaining gas: 1039986.067 units remaining) + [ "" ] + - location: 24 (remaining gas: 1039985.992 units remaining) + [ {} + "" ] + - location: 26 (remaining gas: 1039985.917 units remaining) + [ (Pair {} "") ] + - location: -1 (remaining gas: 1039985.872 units remaining) + [ (Pair {} "") ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cons.tz-{ -5 ; 10 }-99-{ 99 ; -5 ; 10 }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cons.tz-{ -5 ; 10 }-99-{ 99 ; -5 ; 10 }].out new file mode 100644 index 0000000000000000000000000000000000000000..f150a57f250dd7e0bd745c0c6415b04ce73ca29e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cons.tz-{ -5 ; 10 }-99-{ 99 ; -5 ; 10 }].out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[cons.tz-{ -5 ; 10 }-99-{ 99 ; -5 ; 10 }] + +storage + { 99 ; -5 ; 10 } +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.830 units remaining) + [ (Pair 99 { -5 ; 10 }) ] + - location: 8 (remaining gas: 1039993.750 units remaining) + [ 99 @parameter + { -5 ; 10 } @storage ] + - location: 9 (remaining gas: 1039993.670 units remaining) + [ { 99 ; -5 ; 10 } ] + - location: 10 (remaining gas: 1039993.595 units remaining) + [ {} + { 99 ; -5 ; 10 } ] + - location: 12 (remaining gas: 1039993.520 units remaining) + [ (Pair {} { 99 ; -5 ; 10 }) ] + - location: -1 (remaining gas: 1039993.475 units remaining) + [ (Pair {} { 99 ; -5 ; 10 }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cons.tz-{ 10 }--5-{ -5 ; 10 }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cons.tz-{ 10 }--5-{ -5 ; 10 }].out new file mode 100644 index 0000000000000000000000000000000000000000..880b11c33a8b1ca8452ffca092b7aef322ea4965 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cons.tz-{ 10 }--5-{ -5 ; 10 }].out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[cons.tz-{ 10 }--5-{ -5 ; 10 }] + +storage + { -5 ; 10 } +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.070 units remaining) + [ (Pair -5 { 10 }) ] + - location: 8 (remaining gas: 1039993.990 units remaining) + [ -5 @parameter + { 10 } @storage ] + - location: 9 (remaining gas: 1039993.910 units remaining) + [ { -5 ; 10 } ] + - location: 10 (remaining gas: 1039993.835 units remaining) + [ {} + { -5 ; 10 } ] + - location: 12 (remaining gas: 1039993.760 units remaining) + [ (Pair {} { -5 ; 10 }) ] + - location: -1 (remaining gas: 1039993.715 units remaining) + [ (Pair {} { -5 ; 10 }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cons.tz-{}-10-{ 10 }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cons.tz-{}-10-{ 10 }].out new file mode 100644 index 0000000000000000000000000000000000000000..de2b812762871627fd7bb9e29c806c95c8dc5f1e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[cons.tz-{}-10-{ 10 }].out @@ -0,0 +1,24 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[cons.tz-{}-10-{ 10 }] + +storage + { 10 } +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.310 units remaining) + [ (Pair 10 {}) ] + - location: 8 (remaining gas: 1039994.230 units remaining) + [ 10 @parameter + {} @storage ] + - location: 9 (remaining gas: 1039994.150 units remaining) + [ { 10 } ] + - location: 10 (remaining gas: 1039994.075 units remaining) + [ {} + { 10 } ] + - location: 12 (remaining gas: 1039994 units remaining) + [ (Pair {} { 10 }) ] + - location: -1 (remaining gas: 1039993.955 units remaining) + [ (Pair {} { 10 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"A\" } { \"B\" })-(Some False)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"A\" } { \"B\" })-(Some False)].out" new file mode 100644 index 0000000000000000000000000000000000000000..35506c1439c852862e3aebf2012a40350fbb2efc --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"A\" } { \"B\" })-(Some False)].out" @@ -0,0 +1,172 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { "A" } { "B" })-(Some False)] + +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039956.652 units remaining) + [ (Pair (Pair { "A" } { "B" }) None) ] + - location: 12 (remaining gas: 1039956.572 units remaining) + [ (Pair { "A" } { "B" }) @parameter ] + - location: 13 (remaining gas: 1039956.492 units remaining) + [ (Pair { "A" } { "B" }) @parameter + (Pair { "A" } { "B" }) @parameter ] + - location: 14 (remaining gas: 1039956.412 units remaining) + [ { "A" } + (Pair { "A" } { "B" }) @parameter ] + - location: 17 (remaining gas: 1039956.257 units remaining) + [ { "B" } ] + - location: 16 (remaining gas: 1039956.212 units remaining) + [ { "B" } ] + - location: 15 (remaining gas: 1039956.212 units remaining) + [ { "A" } + { "B" } ] + - location: 18 (remaining gas: 1039955.982 units remaining) + [ {} + { "A" } + { "B" } ] + - location: 20 (remaining gas: 1039955.912 units remaining) + [ { "A" } + {} + { "B" } ] + - location: 23 (remaining gas: 1039955.300 units remaining) + [ (Pair "A" {}) + { "B" } ] + - location: 24 (remaining gas: 1039955.220 units remaining) + [ (Pair "A" {}) + (Pair "A" {}) + { "B" } ] + - location: 25 (remaining gas: 1039955.140 units remaining) + [ "A" @elt + (Pair "A" {}) + { "B" } ] + - location: 28 (remaining gas: 1039954.985 units remaining) + [ {} + { "B" } ] + - location: 27 (remaining gas: 1039954.940 units remaining) + [ {} + { "B" } ] + - location: 26 (remaining gas: 1039954.940 units remaining) + [ "A" @elt + {} + { "B" } ] + - location: 29 (remaining gas: 1039954.865 units remaining) + [ True + "A" @elt + {} + { "B" } ] + - location: 32 (remaining gas: 1039954.795 units remaining) + [ "A" @elt + True + {} + { "B" } ] + - location: 33 (remaining gas: 1039954.685 units remaining) + [ { "A" } + { "B" } ] + - location: -1 (remaining gas: 1039954.640 units remaining) + [ { "A" } + { "B" } ] + - location: 21 (remaining gas: 1039954.640 units remaining) + [ { "A" } + { "B" } ] + - location: 34 (remaining gas: 1039954.565 units remaining) + [ True + { "A" } + { "B" } ] + - location: 37 (remaining gas: 1039954.495 units remaining) + [ { "A" } + True + { "B" } ] + - location: 38 (remaining gas: 1039954.420 units remaining) + [ (Pair { "A" } True) + { "B" } ] + - location: 39 (remaining gas: 1039954.350 units remaining) + [ { "B" } + (Pair { "A" } True) ] + - location: 42 (remaining gas: 1039953.738 units remaining) + [ (Pair "B" { "A" } True) ] + - location: 43 (remaining gas: 1039953.658 units remaining) + [ (Pair "B" { "A" } True) + (Pair "B" { "A" } True) ] + - location: 44 (remaining gas: 1039953.578 units remaining) + [ (Pair "B" { "A" } True) + (Pair "B" { "A" } True) + (Pair "B" { "A" } True) ] + - location: 45 (remaining gas: 1039953.498 units remaining) + [ "B" @elt + (Pair "B" { "A" } True) + (Pair "B" { "A" } True) ] + - location: 49 (remaining gas: 1039953.313 units remaining) + [ (Pair { "A" } True) + (Pair "B" { "A" } True) ] + - location: 50 (remaining gas: 1039953.233 units remaining) + [ { "A" } + (Pair "B" { "A" } True) ] + - location: -1 (remaining gas: 1039953.188 units remaining) + [ { "A" } + (Pair "B" { "A" } True) ] + - location: 54 (remaining gas: 1039953.003 units remaining) + [ (Pair { "A" } True) ] + - location: 55 (remaining gas: 1039952.923 units remaining) + [ True ] + - location: -1 (remaining gas: 1039952.878 units remaining) + [ True ] + - location: 52 (remaining gas: 1039952.833 units remaining) + [ True ] + - location: 51 (remaining gas: 1039952.833 units remaining) + [ { "A" } + True ] + - location: 56 (remaining gas: 1039952.753 units remaining) + [ { "A" } + { "A" } + True ] + - location: -1 (remaining gas: 1039952.708 units remaining) + [ { "A" } + { "A" } + True ] + - location: 46 (remaining gas: 1039952.708 units remaining) + [ "B" @elt + { "A" } + { "A" } + True ] + - location: 57 (remaining gas: 1039952.598 units remaining) + [ False + { "A" } + True ] + - location: 60 (remaining gas: 1039952.453 units remaining) + [ True + { "A" } ] + - location: 59 (remaining gas: 1039952.408 units remaining) + [ True + { "A" } ] + - location: 58 (remaining gas: 1039952.408 units remaining) + [ False + True + { "A" } ] + - location: 61 (remaining gas: 1039952.328 units remaining) + [ False + { "A" } ] + - location: 62 (remaining gas: 1039952.258 units remaining) + [ { "A" } + False ] + - location: 63 (remaining gas: 1039952.183 units remaining) + [ (Pair { "A" } False) ] + - location: -1 (remaining gas: 1039952.138 units remaining) + [ (Pair { "A" } False) ] + - location: 40 (remaining gas: 1039952.138 units remaining) + [ (Pair { "A" } False) ] + - location: 64 (remaining gas: 1039952.058 units remaining) + [ False ] + - location: 65 (remaining gas: 1039951.983 units remaining) + [ (Some False) ] + - location: 66 (remaining gas: 1039951.908 units remaining) + [ {} + (Some False) ] + - location: 68 (remaining gas: 1039951.833 units remaining) + [ (Pair {} (Some False)) ] + - location: -1 (remaining gas: 1039951.788 units remaining) + [ (Pair {} (Some False)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"B\" ; \"B\" ; \"asdf\" ; \"C\" }.4360bbe5d0.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"B\" ; \"B\" ; \"asdf\" ; \"C\" }.4360bbe5d0.out" new file mode 100644 index 0000000000000000000000000000000000000000..66141875b66db6defcd50ea956dd82fd871b711d --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"B\" ; \"B\" ; \"asdf\" ; \"C\" }.4360bbe5d0.out" @@ -0,0 +1,423 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" })-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039955.272 units remaining) + [ (Pair (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) None) ] + - location: 12 (remaining gas: 1039955.192 units remaining) + [ (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) @parameter ] + - location: 13 (remaining gas: 1039955.112 units remaining) + [ (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) @parameter + (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) @parameter ] + - location: 14 (remaining gas: 1039955.032 units remaining) + [ { "B" ; "B" ; "asdf" ; "C" } + (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) @parameter ] + - location: 17 (remaining gas: 1039954.877 units remaining) + [ { "B" ; "C" ; "asdf" } ] + - location: 16 (remaining gas: 1039954.832 units remaining) + [ { "B" ; "C" ; "asdf" } ] + - location: 15 (remaining gas: 1039954.832 units remaining) + [ { "B" ; "B" ; "asdf" ; "C" } + { "B" ; "C" ; "asdf" } ] + - location: 18 (remaining gas: 1039954.602 units remaining) + [ {} + { "B" ; "B" ; "asdf" ; "C" } + { "B" ; "C" ; "asdf" } ] + - location: 20 (remaining gas: 1039954.532 units remaining) + [ { "B" ; "B" ; "asdf" ; "C" } + {} + { "B" ; "C" ; "asdf" } ] + - location: 23 (remaining gas: 1039953.899 units remaining) + [ (Pair "B" {}) + { "B" ; "C" ; "asdf" } ] + - location: 24 (remaining gas: 1039953.819 units remaining) + [ (Pair "B" {}) + (Pair "B" {}) + { "B" ; "C" ; "asdf" } ] + - location: 25 (remaining gas: 1039953.739 units remaining) + [ "B" @elt + (Pair "B" {}) + { "B" ; "C" ; "asdf" } ] + - location: 28 (remaining gas: 1039953.584 units remaining) + [ {} + { "B" ; "C" ; "asdf" } ] + - location: 27 (remaining gas: 1039953.539 units remaining) + [ {} + { "B" ; "C" ; "asdf" } ] + - location: 26 (remaining gas: 1039953.539 units remaining) + [ "B" @elt + {} + { "B" ; "C" ; "asdf" } ] + - location: 29 (remaining gas: 1039953.464 units remaining) + [ True + "B" @elt + {} + { "B" ; "C" ; "asdf" } ] + - location: 32 (remaining gas: 1039953.394 units remaining) + [ "B" @elt + True + {} + { "B" ; "C" ; "asdf" } ] + - location: 33 (remaining gas: 1039953.284 units remaining) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: -1 (remaining gas: 1039953.239 units remaining) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 23 (remaining gas: 1039953.164 units remaining) + [ (Pair "B" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 24 (remaining gas: 1039953.084 units remaining) + [ (Pair "B" { "B" }) + (Pair "B" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 25 (remaining gas: 1039953.004 units remaining) + [ "B" @elt + (Pair "B" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 28 (remaining gas: 1039952.849 units remaining) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 27 (remaining gas: 1039952.804 units remaining) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 26 (remaining gas: 1039952.804 units remaining) + [ "B" @elt + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 29 (remaining gas: 1039952.729 units remaining) + [ True + "B" @elt + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 32 (remaining gas: 1039952.659 units remaining) + [ "B" @elt + True + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 33 (remaining gas: 1039952.549 units remaining) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: -1 (remaining gas: 1039952.504 units remaining) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 23 (remaining gas: 1039952.429 units remaining) + [ (Pair "asdf" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 24 (remaining gas: 1039952.349 units remaining) + [ (Pair "asdf" { "B" }) + (Pair "asdf" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 25 (remaining gas: 1039952.269 units remaining) + [ "asdf" @elt + (Pair "asdf" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 28 (remaining gas: 1039952.114 units remaining) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 27 (remaining gas: 1039952.069 units remaining) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 26 (remaining gas: 1039952.069 units remaining) + [ "asdf" @elt + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 29 (remaining gas: 1039951.994 units remaining) + [ True + "asdf" @elt + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 32 (remaining gas: 1039951.924 units remaining) + [ "asdf" @elt + True + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 33 (remaining gas: 1039951.813 units remaining) + [ { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: -1 (remaining gas: 1039951.768 units remaining) + [ { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 23 (remaining gas: 1039951.693 units remaining) + [ (Pair "C" { "B" ; "asdf" }) + { "B" ; "C" ; "asdf" } ] + - location: 24 (remaining gas: 1039951.613 units remaining) + [ (Pair "C" { "B" ; "asdf" }) + (Pair "C" { "B" ; "asdf" }) + { "B" ; "C" ; "asdf" } ] + - location: 25 (remaining gas: 1039951.533 units remaining) + [ "C" @elt + (Pair "C" { "B" ; "asdf" }) + { "B" ; "C" ; "asdf" } ] + - location: 28 (remaining gas: 1039951.378 units remaining) + [ { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 27 (remaining gas: 1039951.333 units remaining) + [ { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 26 (remaining gas: 1039951.333 units remaining) + [ "C" @elt + { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 29 (remaining gas: 1039951.258 units remaining) + [ True + "C" @elt + { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 32 (remaining gas: 1039951.188 units remaining) + [ "C" @elt + True + { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 33 (remaining gas: 1039951.078 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: -1 (remaining gas: 1039951.033 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 21 (remaining gas: 1039951.033 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 34 (remaining gas: 1039950.958 units remaining) + [ True + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 37 (remaining gas: 1039950.888 units remaining) + [ { "B" ; "C" ; "asdf" } + True + { "B" ; "C" ; "asdf" } ] + - location: 38 (remaining gas: 1039950.813 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) + { "B" ; "C" ; "asdf" } ] + - location: 39 (remaining gas: 1039950.743 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (remaining gas: 1039950.117 units remaining) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (remaining gas: 1039950.037 units remaining) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (remaining gas: 1039949.957 units remaining) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (remaining gas: 1039949.877 units remaining) + [ "B" @elt + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (remaining gas: 1039949.692 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (remaining gas: 1039949.612 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039949.567 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (remaining gas: 1039949.382 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (remaining gas: 1039949.302 units remaining) + [ True ] + - location: -1 (remaining gas: 1039949.257 units remaining) + [ True ] + - location: 52 (remaining gas: 1039949.212 units remaining) + [ True ] + - location: 51 (remaining gas: 1039949.212 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (remaining gas: 1039949.132 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: -1 (remaining gas: 1039949.087 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (remaining gas: 1039949.087 units remaining) + [ "B" @elt + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (remaining gas: 1039948.977 units remaining) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 60 (remaining gas: 1039948.832 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 59 (remaining gas: 1039948.787 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (remaining gas: 1039948.787 units remaining) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (remaining gas: 1039948.707 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (remaining gas: 1039948.637 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (remaining gas: 1039948.562 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039948.517 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (remaining gas: 1039948.442 units remaining) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (remaining gas: 1039948.362 units remaining) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (remaining gas: 1039948.282 units remaining) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (remaining gas: 1039948.202 units remaining) + [ "C" @elt + (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (remaining gas: 1039948.017 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (remaining gas: 1039947.937 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039947.892 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (remaining gas: 1039947.707 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (remaining gas: 1039947.627 units remaining) + [ True ] + - location: -1 (remaining gas: 1039947.582 units remaining) + [ True ] + - location: 52 (remaining gas: 1039947.537 units remaining) + [ True ] + - location: 51 (remaining gas: 1039947.537 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (remaining gas: 1039947.457 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: -1 (remaining gas: 1039947.412 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (remaining gas: 1039947.412 units remaining) + [ "C" @elt + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (remaining gas: 1039947.302 units remaining) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 60 (remaining gas: 1039947.157 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 59 (remaining gas: 1039947.112 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (remaining gas: 1039947.112 units remaining) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (remaining gas: 1039947.032 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (remaining gas: 1039946.962 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (remaining gas: 1039946.887 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039946.842 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (remaining gas: 1039946.767 units remaining) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (remaining gas: 1039946.687 units remaining) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (remaining gas: 1039946.607 units remaining) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (remaining gas: 1039946.527 units remaining) + [ "asdf" @elt + (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (remaining gas: 1039946.342 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (remaining gas: 1039946.262 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039946.217 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (remaining gas: 1039946.032 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (remaining gas: 1039945.952 units remaining) + [ True ] + - location: -1 (remaining gas: 1039945.907 units remaining) + [ True ] + - location: 52 (remaining gas: 1039945.862 units remaining) + [ True ] + - location: 51 (remaining gas: 1039945.862 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (remaining gas: 1039945.782 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: -1 (remaining gas: 1039945.737 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (remaining gas: 1039945.737 units remaining) + [ "asdf" @elt + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (remaining gas: 1039945.627 units remaining) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 60 (remaining gas: 1039945.482 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 59 (remaining gas: 1039945.437 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (remaining gas: 1039945.437 units remaining) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (remaining gas: 1039945.357 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (remaining gas: 1039945.287 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (remaining gas: 1039945.212 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039945.167 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (remaining gas: 1039945.167 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 64 (remaining gas: 1039945.087 units remaining) + [ True ] + - location: 65 (remaining gas: 1039945.012 units remaining) + [ (Some True) ] + - location: 66 (remaining gas: 1039944.937 units remaining) + [ {} + (Some True) ] + - location: 68 (remaining gas: 1039944.862 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039944.817 units remaining) + [ (Pair {} (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"B\" ; \"C\" ; \"asdf\" } { \"B\".ff6e4785ee.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"B\" ; \"C\" ; \"asdf\" } { \"B\".ff6e4785ee.out" new file mode 100644 index 0000000000000000000000000000000000000000..8bc1a6cfa441e385d2917c5541a05b63935aa8f0 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"B\" ; \"C\" ; \"asdf\" } { \"B\".ff6e4785ee.out" @@ -0,0 +1,456 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" })-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039955.272 units remaining) + [ (Pair (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) None) ] + - location: 12 (remaining gas: 1039955.192 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) @parameter ] + - location: 13 (remaining gas: 1039955.112 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) @parameter + (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) @parameter ] + - location: 14 (remaining gas: 1039955.032 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) @parameter ] + - location: 17 (remaining gas: 1039954.877 units remaining) + [ { "B" ; "B" ; "asdf" ; "C" } ] + - location: 16 (remaining gas: 1039954.832 units remaining) + [ { "B" ; "B" ; "asdf" ; "C" } ] + - location: 15 (remaining gas: 1039954.832 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 18 (remaining gas: 1039954.602 units remaining) + [ {} + { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 20 (remaining gas: 1039954.532 units remaining) + [ { "B" ; "C" ; "asdf" } + {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 23 (remaining gas: 1039953.906 units remaining) + [ (Pair "B" {}) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 24 (remaining gas: 1039953.826 units remaining) + [ (Pair "B" {}) + (Pair "B" {}) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 25 (remaining gas: 1039953.746 units remaining) + [ "B" @elt + (Pair "B" {}) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 28 (remaining gas: 1039953.591 units remaining) + [ {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 27 (remaining gas: 1039953.546 units remaining) + [ {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 26 (remaining gas: 1039953.546 units remaining) + [ "B" @elt + {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 29 (remaining gas: 1039953.471 units remaining) + [ True + "B" @elt + {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 32 (remaining gas: 1039953.401 units remaining) + [ "B" @elt + True + {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 33 (remaining gas: 1039953.291 units remaining) + [ { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: -1 (remaining gas: 1039953.246 units remaining) + [ { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 23 (remaining gas: 1039953.171 units remaining) + [ (Pair "C" { "B" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 24 (remaining gas: 1039953.091 units remaining) + [ (Pair "C" { "B" }) + (Pair "C" { "B" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 25 (remaining gas: 1039953.011 units remaining) + [ "C" @elt + (Pair "C" { "B" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 28 (remaining gas: 1039952.856 units remaining) + [ { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 27 (remaining gas: 1039952.811 units remaining) + [ { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 26 (remaining gas: 1039952.811 units remaining) + [ "C" @elt + { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 29 (remaining gas: 1039952.736 units remaining) + [ True + "C" @elt + { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 32 (remaining gas: 1039952.666 units remaining) + [ "C" @elt + True + { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 33 (remaining gas: 1039952.556 units remaining) + [ { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: -1 (remaining gas: 1039952.511 units remaining) + [ { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 23 (remaining gas: 1039952.436 units remaining) + [ (Pair "asdf" { "B" ; "C" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 24 (remaining gas: 1039952.356 units remaining) + [ (Pair "asdf" { "B" ; "C" }) + (Pair "asdf" { "B" ; "C" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 25 (remaining gas: 1039952.276 units remaining) + [ "asdf" @elt + (Pair "asdf" { "B" ; "C" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 28 (remaining gas: 1039952.121 units remaining) + [ { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 27 (remaining gas: 1039952.076 units remaining) + [ { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 26 (remaining gas: 1039952.076 units remaining) + [ "asdf" @elt + { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 29 (remaining gas: 1039952.001 units remaining) + [ True + "asdf" @elt + { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 32 (remaining gas: 1039951.931 units remaining) + [ "asdf" @elt + True + { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 33 (remaining gas: 1039951.820 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: -1 (remaining gas: 1039951.775 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 21 (remaining gas: 1039951.775 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 34 (remaining gas: 1039951.700 units remaining) + [ True + { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 37 (remaining gas: 1039951.630 units remaining) + [ { "B" ; "C" ; "asdf" } + True + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 38 (remaining gas: 1039951.555 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 39 (remaining gas: 1039951.485 units remaining) + [ { "B" ; "B" ; "asdf" ; "C" } + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (remaining gas: 1039950.852 units remaining) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (remaining gas: 1039950.772 units remaining) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (remaining gas: 1039950.692 units remaining) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (remaining gas: 1039950.612 units remaining) + [ "B" @elt + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (remaining gas: 1039950.427 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (remaining gas: 1039950.347 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039950.302 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (remaining gas: 1039950.117 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (remaining gas: 1039950.037 units remaining) + [ True ] + - location: -1 (remaining gas: 1039949.992 units remaining) + [ True ] + - location: 52 (remaining gas: 1039949.947 units remaining) + [ True ] + - location: 51 (remaining gas: 1039949.947 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (remaining gas: 1039949.867 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: -1 (remaining gas: 1039949.822 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (remaining gas: 1039949.822 units remaining) + [ "B" @elt + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (remaining gas: 1039949.712 units remaining) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 60 (remaining gas: 1039949.567 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 59 (remaining gas: 1039949.522 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (remaining gas: 1039949.522 units remaining) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (remaining gas: 1039949.442 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (remaining gas: 1039949.372 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (remaining gas: 1039949.297 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039949.252 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (remaining gas: 1039949.177 units remaining) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (remaining gas: 1039949.097 units remaining) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (remaining gas: 1039949.017 units remaining) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (remaining gas: 1039948.937 units remaining) + [ "B" @elt + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (remaining gas: 1039948.752 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (remaining gas: 1039948.672 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039948.627 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (remaining gas: 1039948.442 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (remaining gas: 1039948.362 units remaining) + [ True ] + - location: -1 (remaining gas: 1039948.317 units remaining) + [ True ] + - location: 52 (remaining gas: 1039948.272 units remaining) + [ True ] + - location: 51 (remaining gas: 1039948.272 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (remaining gas: 1039948.192 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: -1 (remaining gas: 1039948.147 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (remaining gas: 1039948.147 units remaining) + [ "B" @elt + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (remaining gas: 1039948.037 units remaining) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 60 (remaining gas: 1039947.892 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 59 (remaining gas: 1039947.847 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (remaining gas: 1039947.847 units remaining) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (remaining gas: 1039947.767 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (remaining gas: 1039947.697 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (remaining gas: 1039947.622 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039947.577 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (remaining gas: 1039947.502 units remaining) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (remaining gas: 1039947.422 units remaining) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (remaining gas: 1039947.342 units remaining) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (remaining gas: 1039947.262 units remaining) + [ "asdf" @elt + (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (remaining gas: 1039947.077 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (remaining gas: 1039946.997 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039946.952 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (remaining gas: 1039946.767 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (remaining gas: 1039946.687 units remaining) + [ True ] + - location: -1 (remaining gas: 1039946.642 units remaining) + [ True ] + - location: 52 (remaining gas: 1039946.597 units remaining) + [ True ] + - location: 51 (remaining gas: 1039946.597 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (remaining gas: 1039946.517 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: -1 (remaining gas: 1039946.472 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (remaining gas: 1039946.472 units remaining) + [ "asdf" @elt + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (remaining gas: 1039946.362 units remaining) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 60 (remaining gas: 1039946.217 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 59 (remaining gas: 1039946.172 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (remaining gas: 1039946.172 units remaining) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (remaining gas: 1039946.092 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (remaining gas: 1039946.022 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (remaining gas: 1039945.947 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039945.902 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (remaining gas: 1039945.827 units remaining) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (remaining gas: 1039945.747 units remaining) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (remaining gas: 1039945.667 units remaining) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (remaining gas: 1039945.587 units remaining) + [ "C" @elt + (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (remaining gas: 1039945.402 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (remaining gas: 1039945.322 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039945.277 units remaining) + [ { "B" ; "C" ; "asdf" } + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (remaining gas: 1039945.092 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (remaining gas: 1039945.012 units remaining) + [ True ] + - location: -1 (remaining gas: 1039944.967 units remaining) + [ True ] + - location: 52 (remaining gas: 1039944.922 units remaining) + [ True ] + - location: 51 (remaining gas: 1039944.922 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (remaining gas: 1039944.842 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: -1 (remaining gas: 1039944.797 units remaining) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (remaining gas: 1039944.797 units remaining) + [ "C" @elt + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (remaining gas: 1039944.687 units remaining) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 60 (remaining gas: 1039944.542 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 59 (remaining gas: 1039944.497 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (remaining gas: 1039944.497 units remaining) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (remaining gas: 1039944.417 units remaining) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (remaining gas: 1039944.347 units remaining) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (remaining gas: 1039944.272 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: -1 (remaining gas: 1039944.227 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (remaining gas: 1039944.227 units remaining) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 64 (remaining gas: 1039944.147 units remaining) + [ True ] + - location: 65 (remaining gas: 1039944.072 units remaining) + [ (Some True) ] + - location: 66 (remaining gas: 1039943.997 units remaining) + [ {} + (Some True) ] + - location: 68 (remaining gas: 1039943.922 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039943.877 units remaining) + [ (Pair {} (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"B\" } { \"B\" })-(Some True)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"B\" } { \"B\" })-(Some True)].out" new file mode 100644 index 0000000000000000000000000000000000000000..a47ef2698a869076c1caaa31261671717bef51b3 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"B\" } { \"B\" })-(Some True)].out" @@ -0,0 +1,172 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { "B" } { "B" })-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039956.652 units remaining) + [ (Pair (Pair { "B" } { "B" }) None) ] + - location: 12 (remaining gas: 1039956.572 units remaining) + [ (Pair { "B" } { "B" }) @parameter ] + - location: 13 (remaining gas: 1039956.492 units remaining) + [ (Pair { "B" } { "B" }) @parameter + (Pair { "B" } { "B" }) @parameter ] + - location: 14 (remaining gas: 1039956.412 units remaining) + [ { "B" } + (Pair { "B" } { "B" }) @parameter ] + - location: 17 (remaining gas: 1039956.257 units remaining) + [ { "B" } ] + - location: 16 (remaining gas: 1039956.212 units remaining) + [ { "B" } ] + - location: 15 (remaining gas: 1039956.212 units remaining) + [ { "B" } + { "B" } ] + - location: 18 (remaining gas: 1039955.982 units remaining) + [ {} + { "B" } + { "B" } ] + - location: 20 (remaining gas: 1039955.912 units remaining) + [ { "B" } + {} + { "B" } ] + - location: 23 (remaining gas: 1039955.300 units remaining) + [ (Pair "B" {}) + { "B" } ] + - location: 24 (remaining gas: 1039955.220 units remaining) + [ (Pair "B" {}) + (Pair "B" {}) + { "B" } ] + - location: 25 (remaining gas: 1039955.140 units remaining) + [ "B" @elt + (Pair "B" {}) + { "B" } ] + - location: 28 (remaining gas: 1039954.985 units remaining) + [ {} + { "B" } ] + - location: 27 (remaining gas: 1039954.940 units remaining) + [ {} + { "B" } ] + - location: 26 (remaining gas: 1039954.940 units remaining) + [ "B" @elt + {} + { "B" } ] + - location: 29 (remaining gas: 1039954.865 units remaining) + [ True + "B" @elt + {} + { "B" } ] + - location: 32 (remaining gas: 1039954.795 units remaining) + [ "B" @elt + True + {} + { "B" } ] + - location: 33 (remaining gas: 1039954.685 units remaining) + [ { "B" } + { "B" } ] + - location: -1 (remaining gas: 1039954.640 units remaining) + [ { "B" } + { "B" } ] + - location: 21 (remaining gas: 1039954.640 units remaining) + [ { "B" } + { "B" } ] + - location: 34 (remaining gas: 1039954.565 units remaining) + [ True + { "B" } + { "B" } ] + - location: 37 (remaining gas: 1039954.495 units remaining) + [ { "B" } + True + { "B" } ] + - location: 38 (remaining gas: 1039954.420 units remaining) + [ (Pair { "B" } True) + { "B" } ] + - location: 39 (remaining gas: 1039954.350 units remaining) + [ { "B" } + (Pair { "B" } True) ] + - location: 42 (remaining gas: 1039953.738 units remaining) + [ (Pair "B" { "B" } True) ] + - location: 43 (remaining gas: 1039953.658 units remaining) + [ (Pair "B" { "B" } True) + (Pair "B" { "B" } True) ] + - location: 44 (remaining gas: 1039953.578 units remaining) + [ (Pair "B" { "B" } True) + (Pair "B" { "B" } True) + (Pair "B" { "B" } True) ] + - location: 45 (remaining gas: 1039953.498 units remaining) + [ "B" @elt + (Pair "B" { "B" } True) + (Pair "B" { "B" } True) ] + - location: 49 (remaining gas: 1039953.313 units remaining) + [ (Pair { "B" } True) + (Pair "B" { "B" } True) ] + - location: 50 (remaining gas: 1039953.233 units remaining) + [ { "B" } + (Pair "B" { "B" } True) ] + - location: -1 (remaining gas: 1039953.188 units remaining) + [ { "B" } + (Pair "B" { "B" } True) ] + - location: 54 (remaining gas: 1039953.003 units remaining) + [ (Pair { "B" } True) ] + - location: 55 (remaining gas: 1039952.923 units remaining) + [ True ] + - location: -1 (remaining gas: 1039952.878 units remaining) + [ True ] + - location: 52 (remaining gas: 1039952.833 units remaining) + [ True ] + - location: 51 (remaining gas: 1039952.833 units remaining) + [ { "B" } + True ] + - location: 56 (remaining gas: 1039952.753 units remaining) + [ { "B" } + { "B" } + True ] + - location: -1 (remaining gas: 1039952.708 units remaining) + [ { "B" } + { "B" } + True ] + - location: 46 (remaining gas: 1039952.708 units remaining) + [ "B" @elt + { "B" } + { "B" } + True ] + - location: 57 (remaining gas: 1039952.598 units remaining) + [ True + { "B" } + True ] + - location: 60 (remaining gas: 1039952.453 units remaining) + [ True + { "B" } ] + - location: 59 (remaining gas: 1039952.408 units remaining) + [ True + { "B" } ] + - location: 58 (remaining gas: 1039952.408 units remaining) + [ True + True + { "B" } ] + - location: 61 (remaining gas: 1039952.328 units remaining) + [ True + { "B" } ] + - location: 62 (remaining gas: 1039952.258 units remaining) + [ { "B" } + True ] + - location: 63 (remaining gas: 1039952.183 units remaining) + [ (Pair { "B" } True) ] + - location: -1 (remaining gas: 1039952.138 units remaining) + [ (Pair { "B" } True) ] + - location: 40 (remaining gas: 1039952.138 units remaining) + [ (Pair { "B" } True) ] + - location: 64 (remaining gas: 1039952.058 units remaining) + [ True ] + - location: 65 (remaining gas: 1039951.983 units remaining) + [ (Some True) ] + - location: 66 (remaining gas: 1039951.908 units remaining) + [ {} + (Some True) ] + - location: 68 (remaining gas: 1039951.833 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039951.788 units remaining) + [ (Pair {} (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"c\" } { \"B\" })-(Some False)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"c\" } { \"B\" })-(Some False)].out" new file mode 100644 index 0000000000000000000000000000000000000000..652ca6d3ec26db8e26748565f2d1e5001107d6a4 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { \"c\" } { \"B\" })-(Some False)].out" @@ -0,0 +1,172 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair { "c" } { "B" })-(Some False)] + +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039956.652 units remaining) + [ (Pair (Pair { "c" } { "B" }) None) ] + - location: 12 (remaining gas: 1039956.572 units remaining) + [ (Pair { "c" } { "B" }) @parameter ] + - location: 13 (remaining gas: 1039956.492 units remaining) + [ (Pair { "c" } { "B" }) @parameter + (Pair { "c" } { "B" }) @parameter ] + - location: 14 (remaining gas: 1039956.412 units remaining) + [ { "c" } + (Pair { "c" } { "B" }) @parameter ] + - location: 17 (remaining gas: 1039956.257 units remaining) + [ { "B" } ] + - location: 16 (remaining gas: 1039956.212 units remaining) + [ { "B" } ] + - location: 15 (remaining gas: 1039956.212 units remaining) + [ { "c" } + { "B" } ] + - location: 18 (remaining gas: 1039955.982 units remaining) + [ {} + { "c" } + { "B" } ] + - location: 20 (remaining gas: 1039955.912 units remaining) + [ { "c" } + {} + { "B" } ] + - location: 23 (remaining gas: 1039955.300 units remaining) + [ (Pair "c" {}) + { "B" } ] + - location: 24 (remaining gas: 1039955.220 units remaining) + [ (Pair "c" {}) + (Pair "c" {}) + { "B" } ] + - location: 25 (remaining gas: 1039955.140 units remaining) + [ "c" @elt + (Pair "c" {}) + { "B" } ] + - location: 28 (remaining gas: 1039954.985 units remaining) + [ {} + { "B" } ] + - location: 27 (remaining gas: 1039954.940 units remaining) + [ {} + { "B" } ] + - location: 26 (remaining gas: 1039954.940 units remaining) + [ "c" @elt + {} + { "B" } ] + - location: 29 (remaining gas: 1039954.865 units remaining) + [ True + "c" @elt + {} + { "B" } ] + - location: 32 (remaining gas: 1039954.795 units remaining) + [ "c" @elt + True + {} + { "B" } ] + - location: 33 (remaining gas: 1039954.685 units remaining) + [ { "c" } + { "B" } ] + - location: -1 (remaining gas: 1039954.640 units remaining) + [ { "c" } + { "B" } ] + - location: 21 (remaining gas: 1039954.640 units remaining) + [ { "c" } + { "B" } ] + - location: 34 (remaining gas: 1039954.565 units remaining) + [ True + { "c" } + { "B" } ] + - location: 37 (remaining gas: 1039954.495 units remaining) + [ { "c" } + True + { "B" } ] + - location: 38 (remaining gas: 1039954.420 units remaining) + [ (Pair { "c" } True) + { "B" } ] + - location: 39 (remaining gas: 1039954.350 units remaining) + [ { "B" } + (Pair { "c" } True) ] + - location: 42 (remaining gas: 1039953.738 units remaining) + [ (Pair "B" { "c" } True) ] + - location: 43 (remaining gas: 1039953.658 units remaining) + [ (Pair "B" { "c" } True) + (Pair "B" { "c" } True) ] + - location: 44 (remaining gas: 1039953.578 units remaining) + [ (Pair "B" { "c" } True) + (Pair "B" { "c" } True) + (Pair "B" { "c" } True) ] + - location: 45 (remaining gas: 1039953.498 units remaining) + [ "B" @elt + (Pair "B" { "c" } True) + (Pair "B" { "c" } True) ] + - location: 49 (remaining gas: 1039953.313 units remaining) + [ (Pair { "c" } True) + (Pair "B" { "c" } True) ] + - location: 50 (remaining gas: 1039953.233 units remaining) + [ { "c" } + (Pair "B" { "c" } True) ] + - location: -1 (remaining gas: 1039953.188 units remaining) + [ { "c" } + (Pair "B" { "c" } True) ] + - location: 54 (remaining gas: 1039953.003 units remaining) + [ (Pair { "c" } True) ] + - location: 55 (remaining gas: 1039952.923 units remaining) + [ True ] + - location: -1 (remaining gas: 1039952.878 units remaining) + [ True ] + - location: 52 (remaining gas: 1039952.833 units remaining) + [ True ] + - location: 51 (remaining gas: 1039952.833 units remaining) + [ { "c" } + True ] + - location: 56 (remaining gas: 1039952.753 units remaining) + [ { "c" } + { "c" } + True ] + - location: -1 (remaining gas: 1039952.708 units remaining) + [ { "c" } + { "c" } + True ] + - location: 46 (remaining gas: 1039952.708 units remaining) + [ "B" @elt + { "c" } + { "c" } + True ] + - location: 57 (remaining gas: 1039952.598 units remaining) + [ False + { "c" } + True ] + - location: 60 (remaining gas: 1039952.453 units remaining) + [ True + { "c" } ] + - location: 59 (remaining gas: 1039952.408 units remaining) + [ True + { "c" } ] + - location: 58 (remaining gas: 1039952.408 units remaining) + [ False + True + { "c" } ] + - location: 61 (remaining gas: 1039952.328 units remaining) + [ False + { "c" } ] + - location: 62 (remaining gas: 1039952.258 units remaining) + [ { "c" } + False ] + - location: 63 (remaining gas: 1039952.183 units remaining) + [ (Pair { "c" } False) ] + - location: -1 (remaining gas: 1039952.138 units remaining) + [ (Pair { "c" } False) ] + - location: 40 (remaining gas: 1039952.138 units remaining) + [ (Pair { "c" } False) ] + - location: 64 (remaining gas: 1039952.058 units remaining) + [ False ] + - location: 65 (remaining gas: 1039951.983 units remaining) + [ (Some False) ] + - location: 66 (remaining gas: 1039951.908 units remaining) + [ {} + (Some False) ] + - location: 68 (remaining gas: 1039951.833 units remaining) + [ (Pair {} (Some False)) ] + - location: -1 (remaining gas: 1039951.788 units remaining) + [ (Pair {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair {} {})-(Some True)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair {} {})-(Some True)].out new file mode 100644 index 0000000000000000000000000000000000000000..73d0b226042fd0cb542814ad00d567d5e576f247 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair {} {})-(Some True)].out @@ -0,0 +1,65 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[contains_all.tz-None-(Pair {} {})-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039957.180 units remaining) + [ (Pair (Pair {} {}) None) ] + - location: 12 (remaining gas: 1039957.100 units remaining) + [ (Pair {} {}) @parameter ] + - location: 13 (remaining gas: 1039957.020 units remaining) + [ (Pair {} {}) @parameter + (Pair {} {}) @parameter ] + - location: 14 (remaining gas: 1039956.940 units remaining) + [ {} + (Pair {} {}) @parameter ] + - location: 17 (remaining gas: 1039956.785 units remaining) + [ {} ] + - location: 16 (remaining gas: 1039956.740 units remaining) + [ {} ] + - location: 15 (remaining gas: 1039956.740 units remaining) + [ {} + {} ] + - location: 18 (remaining gas: 1039956.510 units remaining) + [ {} + {} + {} ] + - location: 20 (remaining gas: 1039956.440 units remaining) + [ {} + {} + {} ] + - location: 21 (remaining gas: 1039955.910 units remaining) + [ {} + {} ] + - location: 34 (remaining gas: 1039955.835 units remaining) + [ True + {} + {} ] + - location: 37 (remaining gas: 1039955.765 units remaining) + [ {} + True + {} ] + - location: 38 (remaining gas: 1039955.690 units remaining) + [ (Pair {} True) + {} ] + - location: 39 (remaining gas: 1039955.620 units remaining) + [ {} + (Pair {} True) ] + - location: 40 (remaining gas: 1039955.090 units remaining) + [ (Pair {} True) ] + - location: 64 (remaining gas: 1039955.010 units remaining) + [ True ] + - location: 65 (remaining gas: 1039954.935 units remaining) + [ (Some True) ] + - location: 66 (remaining gas: 1039954.860 units remaining) + [ {} + (Some True) ] + - location: 68 (remaining gas: 1039954.785 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039954.740 units remaining) + [ (Pair {} (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contract.tz-Unit-\"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5\"-Unit].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contract.tz-Unit-\"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5\"-Unit].out" new file mode 100644 index 0000000000000000000000000000000000000000..40f8a98bf1e37a263c5d95c3ad6b6a41f35ece80 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[contract.tz-Unit-\"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5\"-Unit].out" @@ -0,0 +1,31 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[contract.tz-Unit-"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039931.695 units remaining) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" Unit) ] + - location: 7 (remaining gas: 1039931.615 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @parameter ] + - location: 8 (remaining gas: 1039686.394 units remaining) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @parameter.contract ] + - location: 16 (remaining gas: 1039686.259 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @parameter.contract.some ] + - location: 10 (remaining gas: 1039686.214 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @parameter.contract.some ] + - location: 17 (remaining gas: 1039686.139 units remaining) + [ ] + - location: 18 (remaining gas: 1039686.064 units remaining) + [ Unit ] + - location: 19 (remaining gas: 1039685.989 units remaining) + [ {} + Unit ] + - location: 21 (remaining gas: 1039685.914 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039685.869 units remaining) + [ (Pair {} Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[create_contract.tz-None-Unit-(Some \"KT1Mjjcb6tmSsLm7Cb3.c3984fbc14.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[create_contract.tz-None-Unit-(Some \"KT1Mjjcb6tmSsLm7Cb3.c3984fbc14.out" new file mode 100644 index 0000000000000000000000000000000000000000..1116ec0c1d709529a281951f47e9197a2c83f714 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[create_contract.tz-None-Unit-(Some \"KT1Mjjcb6tmSsLm7Cb3.c3984fbc14.out" @@ -0,0 +1,53 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[create_contract.tz-None-Unit-(Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm")] + +storage + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") +emitted operations + Internal origination: + From: KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi + Credit: ꜩ0.05 + Script: + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + big_map diff + + trace + - location: 7 (remaining gas: 1039985.320 units remaining) + [ (Pair Unit None) ] + - location: 8 (remaining gas: 1039985.245 units remaining) + [ ] + - location: 9 (remaining gas: 1039985.170 units remaining) + [ Unit ] + - location: 10 (remaining gas: 1039985.095 units remaining) + [ 50000 @amount + Unit ] + - location: 11 (remaining gas: 1039985.020 units remaining) + [ None + 50000 @amount + Unit ] + - location: 13 (remaining gas: 1039983.540 units remaining) + [ 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000002d08603000000001c02000000170500036c0501036c050202000000080317053d036d034200000002030b + "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm" ] + - location: 27 (remaining gas: 1039983.390 units remaining) + [ (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") ] + - location: 28 (remaining gas: 1039983.315 units remaining) + [ {} + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") ] + - location: -1 (remaining gas: 1039983.270 units remaining) + [ {} + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") ] + - location: 25 (remaining gas: 1039983.270 units remaining) + [ 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000002d08603000000001c02000000170500036c0501036c050202000000080317053d036d034200000002030b + {} + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") ] + - location: 30 (remaining gas: 1039983.190 units remaining) + [ { 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000002d08603000000001c02000000170500036c0501036c050202000000080317053d036d034200000002030b } + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") ] + - location: 31 (remaining gas: 1039983.115 units remaining) + [ (Pair { 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000002d08603000000001c02000000170500036c0501036c050202000000080317053d036d034200000002030b } + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm")) ] + - location: -1 (remaining gas: 1039983.070 units remaining) + [ (Pair { 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000002d08603000000001c02000000170500036c0501036c050202000000080317053d036d034200000002030b } + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair \"1970-01-01T00:03:20Z\" \"19.90e9215d17.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair \"1970-01-01T00:03:20Z\" \"19.90e9215d17.out" new file mode 100644 index 0000000000000000000000000000000000000000..eda4b3ca67e870f8dc2f16ed63279c67cedc2dda --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair \"1970-01-01T00:03:20Z\" \"19.90e9215d17.out" @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z")-200] + +storage + 200 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039989.940 units remaining) + [ (Pair (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") 111) ] + - location: 9 (remaining gas: 1039989.860 units remaining) + [ (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") @parameter ] + - location: 10 (remaining gas: 1039989.780 units remaining) + [ (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") @parameter + (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") @parameter ] + - location: 11 (remaining gas: 1039989.700 units remaining) + [ "1970-01-01T00:03:20Z" + (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") @parameter ] + - location: 14 (remaining gas: 1039989.545 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 13 (remaining gas: 1039989.500 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 12 (remaining gas: 1039989.500 units remaining) + [ "1970-01-01T00:03:20Z" + "1970-01-01T00:00:00Z" ] + - location: 15 (remaining gas: 1039989.390 units remaining) + [ 200 ] + - location: 16 (remaining gas: 1039989.315 units remaining) + [ {} + 200 ] + - location: 18 (remaining gas: 1039989.240 units remaining) + [ (Pair {} 200) ] + - location: -1 (remaining gas: 1039989.195 units remaining) + [ (Pair {} 200) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 0 0)-0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 0 0)-0].out new file mode 100644 index 0000000000000000000000000000000000000000..ce03d9bac661ae2ec2cbab4dfc96b2bd55c9abe0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 0 0)-0].out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 0 0)-0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039990.200 units remaining) + [ (Pair (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") 111) ] + - location: 9 (remaining gas: 1039990.120 units remaining) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") @parameter ] + - location: 10 (remaining gas: 1039990.040 units remaining) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") @parameter + (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") @parameter ] + - location: 11 (remaining gas: 1039989.960 units remaining) + [ "1970-01-01T00:00:00Z" + (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") @parameter ] + - location: 14 (remaining gas: 1039989.805 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 13 (remaining gas: 1039989.760 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 12 (remaining gas: 1039989.760 units remaining) + [ "1970-01-01T00:00:00Z" + "1970-01-01T00:00:00Z" ] + - location: 15 (remaining gas: 1039989.650 units remaining) + [ 0 ] + - location: 16 (remaining gas: 1039989.575 units remaining) + [ {} + 0 ] + - location: 18 (remaining gas: 1039989.500 units remaining) + [ (Pair {} 0) ] + - location: -1 (remaining gas: 1039989.455 units remaining) + [ (Pair {} 0) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 0 1)--1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 0 1)--1].out new file mode 100644 index 0000000000000000000000000000000000000000..4d7f316377ee475d2f5b46c0bdce2739c73a4d5c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 0 1)--1].out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 0 1)--1] + +storage + -1 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039990.200 units remaining) + [ (Pair (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") 111) ] + - location: 9 (remaining gas: 1039990.120 units remaining) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") @parameter ] + - location: 10 (remaining gas: 1039990.040 units remaining) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") @parameter + (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") @parameter ] + - location: 11 (remaining gas: 1039989.960 units remaining) + [ "1970-01-01T00:00:00Z" + (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") @parameter ] + - location: 14 (remaining gas: 1039989.805 units remaining) + [ "1970-01-01T00:00:01Z" ] + - location: 13 (remaining gas: 1039989.760 units remaining) + [ "1970-01-01T00:00:01Z" ] + - location: 12 (remaining gas: 1039989.760 units remaining) + [ "1970-01-01T00:00:00Z" + "1970-01-01T00:00:01Z" ] + - location: 15 (remaining gas: 1039989.650 units remaining) + [ -1 ] + - location: 16 (remaining gas: 1039989.575 units remaining) + [ {} + -1 ] + - location: 18 (remaining gas: 1039989.500 units remaining) + [ (Pair {} -1) ] + - location: -1 (remaining gas: 1039989.455 units remaining) + [ (Pair {} -1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 1 0)-1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 1 0)-1].out new file mode 100644 index 0000000000000000000000000000000000000000..d5e48711cffa3c1adcbca00f3823546b27107048 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 1 0)-1].out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[diff_timestamps.tz-111-(Pair 1 0)-1] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039990.200 units remaining) + [ (Pair (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") 111) ] + - location: 9 (remaining gas: 1039990.120 units remaining) + [ (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") @parameter ] + - location: 10 (remaining gas: 1039990.040 units remaining) + [ (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") @parameter + (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") @parameter ] + - location: 11 (remaining gas: 1039989.960 units remaining) + [ "1970-01-01T00:00:01Z" + (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") @parameter ] + - location: 14 (remaining gas: 1039989.805 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 13 (remaining gas: 1039989.760 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 12 (remaining gas: 1039989.760 units remaining) + [ "1970-01-01T00:00:01Z" + "1970-01-01T00:00:00Z" ] + - location: 15 (remaining gas: 1039989.650 units remaining) + [ 1 ] + - location: 16 (remaining gas: 1039989.575 units remaining) + [ {} + 1 ] + - location: 18 (remaining gas: 1039989.500 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039989.455 units remaining) + [ (Pair {} 1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dig_eq.tz-Unit-(Pair 17 (Pair 16 (Pair 15 (Pair 14 (Pai.2794d4782e.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dig_eq.tz-Unit-(Pair 17 (Pair 16 (Pair 15 (Pair 14 (Pai.2794d4782e.out new file mode 100644 index 0000000000000000000000000000000000000000..7906e612f83df99887dff237050e0a696d434981 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dig_eq.tz-Unit-(Pair 17 (Pair 16 (Pair 15 (Pair 14 (Pai.2794d4782e.out @@ -0,0 +1,1266 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[dig_eq.tz-Unit-(Pair 17 (Pair 16 (Pair 15 (Pair 14 (Pair 13 (Pair 12 (Pair 11 (Pair 10 (Pair 9 (Pair 8 (Pair 7 (Pair 6 (Pair 5 (Pair 4 (Pair 3 (Pair 2 1))))))))))))))))-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 23 (remaining gas: 1039861.200 units remaining) + [ (Pair (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) Unit) ] + - location: 24 (remaining gas: 1039861.120 units remaining) + [ (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 25 (remaining gas: 1039861.040 units remaining) + [ (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 27 (remaining gas: 1039860.930 units remaining) + [ 17 + (Pair 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 30 (remaining gas: 1039860.775 units remaining) + [ 16 + (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 29 (remaining gas: 1039860.730 units remaining) + [ 16 + (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 28 (remaining gas: 1039860.730 units remaining) + [ 17 + 16 + (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 34 (remaining gas: 1039860.512 units remaining) + [ 15 + (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 33 (remaining gas: 1039860.467 units remaining) + [ 15 + (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 31 (remaining gas: 1039860.467 units remaining) + [ 17 + 16 + 15 + (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 38 (remaining gas: 1039860.245 units remaining) + [ 14 + (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 37 (remaining gas: 1039860.200 units remaining) + [ 14 + (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 35 (remaining gas: 1039860.200 units remaining) + [ 17 + 16 + 15 + 14 + (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 42 (remaining gas: 1039859.974 units remaining) + [ 13 + (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 41 (remaining gas: 1039859.929 units remaining) + [ 13 + (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 39 (remaining gas: 1039859.929 units remaining) + [ 17 + 16 + 15 + 14 + 13 + (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 46 (remaining gas: 1039859.699 units remaining) + [ 12 + (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 45 (remaining gas: 1039859.654 units remaining) + [ 12 + (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 43 (remaining gas: 1039859.654 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 50 (remaining gas: 1039859.420 units remaining) + [ 11 + (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 49 (remaining gas: 1039859.375 units remaining) + [ 11 + (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 47 (remaining gas: 1039859.375 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 54 (remaining gas: 1039859.137 units remaining) + [ 10 + (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 53 (remaining gas: 1039859.092 units remaining) + [ 10 + (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 51 (remaining gas: 1039859.092 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 58 (remaining gas: 1039858.850 units remaining) + [ 9 + (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 57 (remaining gas: 1039858.805 units remaining) + [ 9 + (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 55 (remaining gas: 1039858.805 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 62 (remaining gas: 1039858.559 units remaining) + [ 8 + (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 61 (remaining gas: 1039858.514 units remaining) + [ 8 + (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 59 (remaining gas: 1039858.514 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 66 (remaining gas: 1039858.264 units remaining) + [ 7 + (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 65 (remaining gas: 1039858.219 units remaining) + [ 7 + (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 63 (remaining gas: 1039858.219 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 70 (remaining gas: 1039857.965 units remaining) + [ 6 + (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 69 (remaining gas: 1039857.920 units remaining) + [ 6 + (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 67 (remaining gas: 1039857.920 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 74 (remaining gas: 1039857.662 units remaining) + [ 5 + (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 73 (remaining gas: 1039857.617 units remaining) + [ 5 + (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 71 (remaining gas: 1039857.617 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 78 (remaining gas: 1039857.355 units remaining) + [ 4 + (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 77 (remaining gas: 1039857.310 units remaining) + [ 4 + (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 75 (remaining gas: 1039857.310 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 82 (remaining gas: 1039857.044 units remaining) + [ 3 + (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 81 (remaining gas: 1039856.999 units remaining) + [ 3 + (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 79 (remaining gas: 1039856.999 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 86 (remaining gas: 1039856.729 units remaining) + [ 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 85 (remaining gas: 1039856.684 units remaining) + [ 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 83 (remaining gas: 1039856.684 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: -1 (remaining gas: 1039856.639 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 87 (remaining gas: 1039856.509 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 89 (remaining gas: 1039856.375 units remaining) + [ 16 + 17 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 91 (remaining gas: 1039856.237 units remaining) + [ 15 + 16 + 17 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 93 (remaining gas: 1039856.095 units remaining) + [ 14 + 15 + 16 + 17 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 95 (remaining gas: 1039855.949 units remaining) + [ 13 + 14 + 15 + 16 + 17 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 97 (remaining gas: 1039855.799 units remaining) + [ 12 + 13 + 14 + 15 + 16 + 17 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 99 (remaining gas: 1039855.645 units remaining) + [ 11 + 12 + 13 + 14 + 15 + 16 + 17 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 101 (remaining gas: 1039855.487 units remaining) + [ 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 103 (remaining gas: 1039855.325 units remaining) + [ 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 105 (remaining gas: 1039855.159 units remaining) + [ 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 107 (remaining gas: 1039854.989 units remaining) + [ 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 109 (remaining gas: 1039854.815 units remaining) + [ 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 111 (remaining gas: 1039854.637 units remaining) + [ 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 113 (remaining gas: 1039854.455 units remaining) + [ 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 115 (remaining gas: 1039854.269 units remaining) + [ 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 117 (remaining gas: 1039854.079 units remaining) + [ 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 119 (remaining gas: 1039853.885 units remaining) + [ 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 121 (remaining gas: 1039853.755 units remaining) + [ 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 123 (remaining gas: 1039853.621 units remaining) + [ 2 + 1 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 125 (remaining gas: 1039853.483 units remaining) + [ 3 + 2 + 1 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 127 (remaining gas: 1039853.341 units remaining) + [ 4 + 3 + 2 + 1 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 129 (remaining gas: 1039853.195 units remaining) + [ 5 + 4 + 3 + 2 + 1 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 131 (remaining gas: 1039853.045 units remaining) + [ 6 + 5 + 4 + 3 + 2 + 1 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 133 (remaining gas: 1039852.891 units remaining) + [ 7 + 6 + 5 + 4 + 3 + 2 + 1 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 135 (remaining gas: 1039852.733 units remaining) + [ 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 137 (remaining gas: 1039852.571 units remaining) + [ 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 139 (remaining gas: 1039852.405 units remaining) + [ 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 141 (remaining gas: 1039852.235 units remaining) + [ 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 143 (remaining gas: 1039852.061 units remaining) + [ 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 145 (remaining gas: 1039851.883 units remaining) + [ 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 147 (remaining gas: 1039851.701 units remaining) + [ 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 149 (remaining gas: 1039851.515 units remaining) + [ 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 151 (remaining gas: 1039851.325 units remaining) + [ 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 153 (remaining gas: 1039851.131 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 159 (remaining gas: 1039850.836 units remaining) + [ (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 158 (remaining gas: 1039850.791 units remaining) + [ (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 156 (remaining gas: 1039850.791 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 163 (remaining gas: 1039850.530 units remaining) + [ (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 162 (remaining gas: 1039850.485 units remaining) + [ (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 160 (remaining gas: 1039850.485 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 167 (remaining gas: 1039850.228 units remaining) + [ (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 166 (remaining gas: 1039850.183 units remaining) + [ (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 164 (remaining gas: 1039850.183 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 171 (remaining gas: 1039849.930 units remaining) + [ (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 170 (remaining gas: 1039849.885 units remaining) + [ (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 168 (remaining gas: 1039849.885 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 175 (remaining gas: 1039849.636 units remaining) + [ (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 174 (remaining gas: 1039849.591 units remaining) + [ (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 172 (remaining gas: 1039849.591 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 179 (remaining gas: 1039849.346 units remaining) + [ (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 178 (remaining gas: 1039849.301 units remaining) + [ (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 176 (remaining gas: 1039849.301 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 183 (remaining gas: 1039849.060 units remaining) + [ (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 182 (remaining gas: 1039849.015 units remaining) + [ (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 180 (remaining gas: 1039849.015 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 187 (remaining gas: 1039848.778 units remaining) + [ (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 186 (remaining gas: 1039848.733 units remaining) + [ (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 184 (remaining gas: 1039848.733 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 191 (remaining gas: 1039848.500 units remaining) + [ (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 190 (remaining gas: 1039848.455 units remaining) + [ (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 188 (remaining gas: 1039848.455 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 195 (remaining gas: 1039848.226 units remaining) + [ (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 194 (remaining gas: 1039848.181 units remaining) + [ (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 192 (remaining gas: 1039848.181 units remaining) + [ 17 + 16 + 15 + 14 + 13 + 12 + (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 199 (remaining gas: 1039847.956 units remaining) + [ (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 198 (remaining gas: 1039847.911 units remaining) + [ (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 196 (remaining gas: 1039847.911 units remaining) + [ 17 + 16 + 15 + 14 + 13 + (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 203 (remaining gas: 1039847.690 units remaining) + [ (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 202 (remaining gas: 1039847.645 units remaining) + [ (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 200 (remaining gas: 1039847.645 units remaining) + [ 17 + 16 + 15 + 14 + (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 207 (remaining gas: 1039847.428 units remaining) + [ (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 206 (remaining gas: 1039847.383 units remaining) + [ (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 204 (remaining gas: 1039847.383 units remaining) + [ 17 + 16 + 15 + (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 211 (remaining gas: 1039847.170 units remaining) + [ (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 210 (remaining gas: 1039847.125 units remaining) + [ (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 208 (remaining gas: 1039847.125 units remaining) + [ 17 + 16 + (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 214 (remaining gas: 1039846.975 units remaining) + [ (Pair 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 213 (remaining gas: 1039846.930 units remaining) + [ (Pair 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 212 (remaining gas: 1039846.930 units remaining) + [ 17 + (Pair 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 215 (remaining gas: 1039846.855 units remaining) + [ (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: -1 (remaining gas: 1039846.810 units remaining) + [ (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) @parameter ] + - location: 218 (remaining gas: 1039844.170 units remaining) + [ 0 ] + - location: 219 (remaining gas: 1039844.095 units remaining) + [ True ] + - location: -1 (remaining gas: 1039844.050 units remaining) + [ True ] + - location: 221 (remaining gas: 1039843.950 units remaining) + [ ] + - location: -1 (remaining gas: 1039843.905 units remaining) + [ ] + - location: 226 (remaining gas: 1039843.830 units remaining) + [ Unit ] + - location: 227 (remaining gas: 1039843.755 units remaining) + [ {} + Unit ] + - location: 229 (remaining gas: 1039843.680 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039843.635 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dig_eq.tz-Unit-(Pair 2 (Pair 3 (Pair 12 (Pair 16 (Pair .d473151c0f.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dig_eq.tz-Unit-(Pair 2 (Pair 3 (Pair 12 (Pair 16 (Pair .d473151c0f.out new file mode 100644 index 0000000000000000000000000000000000000000..e57b2beba4c9ccf55239aa28b222c060065e04f4 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dig_eq.tz-Unit-(Pair 2 (Pair 3 (Pair 12 (Pair 16 (Pair .d473151c0f.out @@ -0,0 +1,1266 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[dig_eq.tz-Unit-(Pair 2 (Pair 3 (Pair 12 (Pair 16 (Pair 10 (Pair 14 (Pair 19 (Pair 9 (Pair 18 (Pair 6 (Pair 8 (Pair 11 (Pair 4 (Pair 13 (Pair 15 (Pair 5 1))))))))))))))))-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 23 (remaining gas: 1039861.200 units remaining) + [ (Pair (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) Unit) ] + - location: 24 (remaining gas: 1039861.120 units remaining) + [ (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 25 (remaining gas: 1039861.040 units remaining) + [ (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 27 (remaining gas: 1039860.930 units remaining) + [ 2 + (Pair 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 30 (remaining gas: 1039860.775 units remaining) + [ 3 + (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 29 (remaining gas: 1039860.730 units remaining) + [ 3 + (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 28 (remaining gas: 1039860.730 units remaining) + [ 2 + 3 + (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 34 (remaining gas: 1039860.512 units remaining) + [ 12 + (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 33 (remaining gas: 1039860.467 units remaining) + [ 12 + (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 31 (remaining gas: 1039860.467 units remaining) + [ 2 + 3 + 12 + (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 38 (remaining gas: 1039860.245 units remaining) + [ 16 + (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 37 (remaining gas: 1039860.200 units remaining) + [ 16 + (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 35 (remaining gas: 1039860.200 units remaining) + [ 2 + 3 + 12 + 16 + (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 42 (remaining gas: 1039859.974 units remaining) + [ 10 + (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 41 (remaining gas: 1039859.929 units remaining) + [ 10 + (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 39 (remaining gas: 1039859.929 units remaining) + [ 2 + 3 + 12 + 16 + 10 + (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 46 (remaining gas: 1039859.699 units remaining) + [ 14 + (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 45 (remaining gas: 1039859.654 units remaining) + [ 14 + (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 43 (remaining gas: 1039859.654 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 50 (remaining gas: 1039859.420 units remaining) + [ 19 + (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 49 (remaining gas: 1039859.375 units remaining) + [ 19 + (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 47 (remaining gas: 1039859.375 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 54 (remaining gas: 1039859.137 units remaining) + [ 9 + (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 53 (remaining gas: 1039859.092 units remaining) + [ 9 + (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 51 (remaining gas: 1039859.092 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 58 (remaining gas: 1039858.850 units remaining) + [ 18 + (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 57 (remaining gas: 1039858.805 units remaining) + [ 18 + (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 55 (remaining gas: 1039858.805 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 62 (remaining gas: 1039858.559 units remaining) + [ 6 + (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 61 (remaining gas: 1039858.514 units remaining) + [ 6 + (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 59 (remaining gas: 1039858.514 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 66 (remaining gas: 1039858.264 units remaining) + [ 8 + (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 65 (remaining gas: 1039858.219 units remaining) + [ 8 + (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 63 (remaining gas: 1039858.219 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 70 (remaining gas: 1039857.965 units remaining) + [ 11 + (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 69 (remaining gas: 1039857.920 units remaining) + [ 11 + (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 67 (remaining gas: 1039857.920 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 74 (remaining gas: 1039857.662 units remaining) + [ 4 + (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 73 (remaining gas: 1039857.617 units remaining) + [ 4 + (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 71 (remaining gas: 1039857.617 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 78 (remaining gas: 1039857.355 units remaining) + [ 13 + (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 77 (remaining gas: 1039857.310 units remaining) + [ 13 + (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 75 (remaining gas: 1039857.310 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 82 (remaining gas: 1039857.044 units remaining) + [ 15 + (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 81 (remaining gas: 1039856.999 units remaining) + [ 15 + (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 79 (remaining gas: 1039856.999 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 86 (remaining gas: 1039856.729 units remaining) + [ 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 85 (remaining gas: 1039856.684 units remaining) + [ 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 83 (remaining gas: 1039856.684 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: -1 (remaining gas: 1039856.639 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 87 (remaining gas: 1039856.509 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 89 (remaining gas: 1039856.375 units remaining) + [ 3 + 2 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 91 (remaining gas: 1039856.237 units remaining) + [ 12 + 3 + 2 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 93 (remaining gas: 1039856.095 units remaining) + [ 16 + 12 + 3 + 2 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 95 (remaining gas: 1039855.949 units remaining) + [ 10 + 16 + 12 + 3 + 2 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 97 (remaining gas: 1039855.799 units remaining) + [ 14 + 10 + 16 + 12 + 3 + 2 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 99 (remaining gas: 1039855.645 units remaining) + [ 19 + 14 + 10 + 16 + 12 + 3 + 2 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 101 (remaining gas: 1039855.487 units remaining) + [ 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 103 (remaining gas: 1039855.325 units remaining) + [ 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 105 (remaining gas: 1039855.159 units remaining) + [ 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 107 (remaining gas: 1039854.989 units remaining) + [ 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 109 (remaining gas: 1039854.815 units remaining) + [ 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 111 (remaining gas: 1039854.637 units remaining) + [ 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 113 (remaining gas: 1039854.455 units remaining) + [ 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 115 (remaining gas: 1039854.269 units remaining) + [ 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 117 (remaining gas: 1039854.079 units remaining) + [ 5 + 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 119 (remaining gas: 1039853.885 units remaining) + [ 1 + 5 + 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 121 (remaining gas: 1039853.755 units remaining) + [ 1 + 5 + 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 123 (remaining gas: 1039853.621 units remaining) + [ 5 + 1 + 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 125 (remaining gas: 1039853.483 units remaining) + [ 15 + 5 + 1 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 127 (remaining gas: 1039853.341 units remaining) + [ 13 + 15 + 5 + 1 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 129 (remaining gas: 1039853.195 units remaining) + [ 4 + 13 + 15 + 5 + 1 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 131 (remaining gas: 1039853.045 units remaining) + [ 11 + 4 + 13 + 15 + 5 + 1 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 133 (remaining gas: 1039852.891 units remaining) + [ 8 + 11 + 4 + 13 + 15 + 5 + 1 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 135 (remaining gas: 1039852.733 units remaining) + [ 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 137 (remaining gas: 1039852.571 units remaining) + [ 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 139 (remaining gas: 1039852.405 units remaining) + [ 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 141 (remaining gas: 1039852.235 units remaining) + [ 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 143 (remaining gas: 1039852.061 units remaining) + [ 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 145 (remaining gas: 1039851.883 units remaining) + [ 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 147 (remaining gas: 1039851.701 units remaining) + [ 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 149 (remaining gas: 1039851.515 units remaining) + [ 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 151 (remaining gas: 1039851.325 units remaining) + [ 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 153 (remaining gas: 1039851.131 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 159 (remaining gas: 1039850.836 units remaining) + [ (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 158 (remaining gas: 1039850.791 units remaining) + [ (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 156 (remaining gas: 1039850.791 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 163 (remaining gas: 1039850.530 units remaining) + [ (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 162 (remaining gas: 1039850.485 units remaining) + [ (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 160 (remaining gas: 1039850.485 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 167 (remaining gas: 1039850.228 units remaining) + [ (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 166 (remaining gas: 1039850.183 units remaining) + [ (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 164 (remaining gas: 1039850.183 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 171 (remaining gas: 1039849.930 units remaining) + [ (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 170 (remaining gas: 1039849.885 units remaining) + [ (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 168 (remaining gas: 1039849.885 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 175 (remaining gas: 1039849.636 units remaining) + [ (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 174 (remaining gas: 1039849.591 units remaining) + [ (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 172 (remaining gas: 1039849.591 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 179 (remaining gas: 1039849.346 units remaining) + [ (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 178 (remaining gas: 1039849.301 units remaining) + [ (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 176 (remaining gas: 1039849.301 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 183 (remaining gas: 1039849.060 units remaining) + [ (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 182 (remaining gas: 1039849.015 units remaining) + [ (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 180 (remaining gas: 1039849.015 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 187 (remaining gas: 1039848.778 units remaining) + [ (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 186 (remaining gas: 1039848.733 units remaining) + [ (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 184 (remaining gas: 1039848.733 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 191 (remaining gas: 1039848.500 units remaining) + [ (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 190 (remaining gas: 1039848.455 units remaining) + [ (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 188 (remaining gas: 1039848.455 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 195 (remaining gas: 1039848.226 units remaining) + [ (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 194 (remaining gas: 1039848.181 units remaining) + [ (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 192 (remaining gas: 1039848.181 units remaining) + [ 2 + 3 + 12 + 16 + 10 + 14 + (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 199 (remaining gas: 1039847.956 units remaining) + [ (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 198 (remaining gas: 1039847.911 units remaining) + [ (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 196 (remaining gas: 1039847.911 units remaining) + [ 2 + 3 + 12 + 16 + 10 + (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 203 (remaining gas: 1039847.690 units remaining) + [ (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 202 (remaining gas: 1039847.645 units remaining) + [ (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 200 (remaining gas: 1039847.645 units remaining) + [ 2 + 3 + 12 + 16 + (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 207 (remaining gas: 1039847.428 units remaining) + [ (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 206 (remaining gas: 1039847.383 units remaining) + [ (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 204 (remaining gas: 1039847.383 units remaining) + [ 2 + 3 + 12 + (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 211 (remaining gas: 1039847.170 units remaining) + [ (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 210 (remaining gas: 1039847.125 units remaining) + [ (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 208 (remaining gas: 1039847.125 units remaining) + [ 2 + 3 + (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 214 (remaining gas: 1039846.975 units remaining) + [ (Pair 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 213 (remaining gas: 1039846.930 units remaining) + [ (Pair 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 212 (remaining gas: 1039846.930 units remaining) + [ 2 + (Pair 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 215 (remaining gas: 1039846.855 units remaining) + [ (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: -1 (remaining gas: 1039846.810 units remaining) + [ (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) @parameter ] + - location: 218 (remaining gas: 1039844.170 units remaining) + [ 0 ] + - location: 219 (remaining gas: 1039844.095 units remaining) + [ True ] + - location: -1 (remaining gas: 1039844.050 units remaining) + [ True ] + - location: 221 (remaining gas: 1039843.950 units remaining) + [ ] + - location: -1 (remaining gas: 1039843.905 units remaining) + [ ] + - location: 226 (remaining gas: 1039843.830 units remaining) + [ Unit ] + - location: 227 (remaining gas: 1039843.755 units remaining) + [ {} + Unit ] + - location: 229 (remaining gas: 1039843.680 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039843.635 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dign.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-5].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dign.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-5].out new file mode 100644 index 0000000000000000000000000000000000000000..27751ac77b18eb5b9f2b15828fe515109f7b8776 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dign.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-5].out @@ -0,0 +1,60 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[dign.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-5] + +storage + 5 +emitted operations + +big_map diff + +trace + - location: 14 (remaining gas: 1039984.510 units remaining) + [ (Pair (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) 0) ] + - location: 15 (remaining gas: 1039984.430 units remaining) + [ (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) @parameter ] + - location: 16 (remaining gas: 1039984.350 units remaining) + [ (Pair (Pair (Pair 1 2) 3) 4) + 5 ] + - location: 17 (remaining gas: 1039984.270 units remaining) + [ (Pair (Pair 1 2) 3) + 4 + 5 ] + - location: 18 (remaining gas: 1039984.190 units remaining) + [ (Pair 1 2) + 3 + 4 + 5 ] + - location: 19 (remaining gas: 1039984.110 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 20 (remaining gas: 1039983.964 units remaining) + [ 5 + 1 + 2 + 3 + 4 ] + - location: 24 (remaining gas: 1039983.814 units remaining) + [ 2 + 3 + 4 ] + - location: 25 (remaining gas: 1039983.739 units remaining) + [ 3 + 4 ] + - location: 26 (remaining gas: 1039983.664 units remaining) + [ 4 ] + - location: 27 (remaining gas: 1039983.589 units remaining) + [ ] + - location: -1 (remaining gas: 1039983.544 units remaining) + [ ] + - location: 22 (remaining gas: 1039983.544 units remaining) + [ 5 ] + - location: 28 (remaining gas: 1039983.469 units remaining) + [ {} + 5 ] + - location: 30 (remaining gas: 1039983.394 units remaining) + [ (Pair {} 5) ] + - location: -1 (remaining gas: 1039983.349 units remaining) + [ (Pair {} 5) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dip.tz-(Pair 0 0)-(Pair 1 1)-(Pair 1 2)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dip.tz-(Pair 0 0)-(Pair 1 1)-(Pair 1 2)].out new file mode 100644 index 0000000000000000000000000000000000000000..66c4eacddd7ce73e59cd5491bec74e75ce434d13 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dip.tz-(Pair 0 0)-(Pair 1 1)-(Pair 1 2)].out @@ -0,0 +1,37 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[dip.tz-(Pair 0 0)-(Pair 1 1)-(Pair 1 2)] + +storage + (Pair 1 2) +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039989.600 units remaining) + [ (Pair (Pair 1 1) 0 0) ] + - location: 11 (remaining gas: 1039989.520 units remaining) + [ (Pair 1 1) @parameter ] + - location: 12 (remaining gas: 1039989.440 units remaining) + [ 1 + 1 ] + - location: 13 (remaining gas: 1039989.360 units remaining) + [ 1 + 1 + 1 ] + - location: 16 (remaining gas: 1039989.175 units remaining) + [ 2 ] + - location: 15 (remaining gas: 1039989.130 units remaining) + [ 2 ] + - location: 14 (remaining gas: 1039989.130 units remaining) + [ 1 + 2 ] + - location: 17 (remaining gas: 1039989.055 units remaining) + [ (Pair 1 2) ] + - location: 18 (remaining gas: 1039988.980 units remaining) + [ {} + (Pair 1 2) ] + - location: 20 (remaining gas: 1039988.905 units remaining) + [ (Pair {} 1 2) ] + - location: -1 (remaining gas: 1039988.860 units remaining) + [ (Pair {} 1 2) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dip.tz-(Pair 0 0)-(Pair 15 9)-(Pair 15 24)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dip.tz-(Pair 0 0)-(Pair 15 9)-(Pair 15 24)].out new file mode 100644 index 0000000000000000000000000000000000000000..42b1477cfeafac9554bd2499686741d05d2b3754 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dip.tz-(Pair 0 0)-(Pair 15 9)-(Pair 15 24)].out @@ -0,0 +1,37 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[dip.tz-(Pair 0 0)-(Pair 15 9)-(Pair 15 24)] + +storage + (Pair 15 24) +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039989.600 units remaining) + [ (Pair (Pair 15 9) 0 0) ] + - location: 11 (remaining gas: 1039989.520 units remaining) + [ (Pair 15 9) @parameter ] + - location: 12 (remaining gas: 1039989.440 units remaining) + [ 15 + 9 ] + - location: 13 (remaining gas: 1039989.360 units remaining) + [ 15 + 15 + 9 ] + - location: 16 (remaining gas: 1039989.175 units remaining) + [ 24 ] + - location: 15 (remaining gas: 1039989.130 units remaining) + [ 24 ] + - location: 14 (remaining gas: 1039989.130 units remaining) + [ 15 + 24 ] + - location: 17 (remaining gas: 1039989.055 units remaining) + [ (Pair 15 24) ] + - location: 18 (remaining gas: 1039988.980 units remaining) + [ {} + (Pair 15 24) ] + - location: 20 (remaining gas: 1039988.905 units remaining) + [ (Pair {} 15 24) ] + - location: -1 (remaining gas: 1039988.860 units remaining) + [ (Pair {} 15 24) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dipn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-6].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dipn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-6].out new file mode 100644 index 0000000000000000000000000000000000000000..eb7787dc5f81bcfdf2b35f16a9495c8086dd17b4 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dipn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-6].out @@ -0,0 +1,70 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[dipn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-6] + +storage + 6 +emitted operations + +big_map diff + +trace + - location: 14 (remaining gas: 1039983.300 units remaining) + [ (Pair (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) 0) ] + - location: 15 (remaining gas: 1039983.220 units remaining) + [ (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) @parameter ] + - location: 16 (remaining gas: 1039983.140 units remaining) + [ (Pair (Pair (Pair 1 2) 3) 4) + 5 ] + - location: 17 (remaining gas: 1039983.060 units remaining) + [ (Pair (Pair 1 2) 3) + 4 + 5 ] + - location: 18 (remaining gas: 1039982.980 units remaining) + [ (Pair 1 2) + 3 + 4 + 5 ] + - location: 19 (remaining gas: 1039982.900 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 23 (remaining gas: 1039982.675 units remaining) + [ 6 ] + - location: 22 (remaining gas: 1039982.630 units remaining) + [ 6 ] + - location: 20 (remaining gas: 1039982.630 units remaining) + [ 1 + 2 + 3 + 4 + 5 + 6 ] + - location: 26 (remaining gas: 1039982.555 units remaining) + [ 2 + 3 + 4 + 5 + 6 ] + - location: 27 (remaining gas: 1039982.480 units remaining) + [ 3 + 4 + 5 + 6 ] + - location: 28 (remaining gas: 1039982.405 units remaining) + [ 4 + 5 + 6 ] + - location: 29 (remaining gas: 1039982.330 units remaining) + [ 5 + 6 ] + - location: 30 (remaining gas: 1039982.255 units remaining) + [ 6 ] + - location: 31 (remaining gas: 1039982.180 units remaining) + [ {} + 6 ] + - location: 33 (remaining gas: 1039982.105 units remaining) + [ (Pair {} 6) ] + - location: -1 (remaining gas: 1039982.060 units remaining) + [ (Pair {} 6) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dropn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-5].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dropn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-5].out new file mode 100644 index 0000000000000000000000000000000000000000..e72bbe78e5a20b8576812aca57b96f2cb3271f66 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dropn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-5].out @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[dropn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-5] + +storage + 5 +emitted operations + +big_map diff + +trace + - location: 14 (remaining gas: 1039988.260 units remaining) + [ (Pair (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) 0) ] + - location: 15 (remaining gas: 1039988.180 units remaining) + [ (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) @parameter ] + - location: 16 (remaining gas: 1039988.100 units remaining) + [ (Pair (Pair (Pair 1 2) 3) 4) + 5 ] + - location: 17 (remaining gas: 1039988.020 units remaining) + [ (Pair (Pair 1 2) 3) + 4 + 5 ] + - location: 18 (remaining gas: 1039987.940 units remaining) + [ (Pair 1 2) + 3 + 4 + 5 ] + - location: 19 (remaining gas: 1039987.860 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 20 (remaining gas: 1039987.714 units remaining) + [ 5 ] + - location: 22 (remaining gas: 1039987.639 units remaining) + [ {} + 5 ] + - location: 24 (remaining gas: 1039987.564 units remaining) + [ (Pair {} 5) ] + - location: -1 (remaining gas: 1039987.519 units remaining) + [ (Pair {} 5) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dugn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dugn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-1].out new file mode 100644 index 0000000000000000000000000000000000000000..955a4e3bfc9a21e161928214079fd88bc3fb5507 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dugn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-1].out @@ -0,0 +1,59 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[dugn.tz-0-(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)-1] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 14 (remaining gas: 1039985.260 units remaining) + [ (Pair (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) 0) ] + - location: 15 (remaining gas: 1039985.180 units remaining) + [ (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) @parameter ] + - location: 16 (remaining gas: 1039985.100 units remaining) + [ (Pair (Pair (Pair 1 2) 3) 4) + 5 ] + - location: 17 (remaining gas: 1039985.020 units remaining) + [ (Pair (Pair 1 2) 3) + 4 + 5 ] + - location: 18 (remaining gas: 1039984.940 units remaining) + [ (Pair 1 2) + 3 + 4 + 5 ] + - location: 19 (remaining gas: 1039984.860 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 20 (remaining gas: 1039984.714 units remaining) + [ 2 + 3 + 4 + 5 + 1 ] + - location: 22 (remaining gas: 1039984.639 units remaining) + [ 3 + 4 + 5 + 1 ] + - location: 23 (remaining gas: 1039984.564 units remaining) + [ 4 + 5 + 1 ] + - location: 24 (remaining gas: 1039984.489 units remaining) + [ 5 + 1 ] + - location: 25 (remaining gas: 1039984.414 units remaining) + [ 1 ] + - location: 26 (remaining gas: 1039984.339 units remaining) + [ {} + 1 ] + - location: 28 (remaining gas: 1039984.264 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039984.219 units remaining) + [ (Pair {} 1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dup-n.tz-Unit-Unit-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dup-n.tz-Unit-Unit-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..2c8e137dd9ce8039bbe4d6e7e114e535cef8873a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[dup-n.tz-Unit-Unit-Unit].out @@ -0,0 +1,285 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[dup-n.tz-Unit-Unit-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039948.940 units remaining) + [ (Pair Unit Unit) ] + - location: 7 (remaining gas: 1039948.865 units remaining) + [ ] + - location: 8 (remaining gas: 1039948.790 units remaining) + [ 5 ] + - location: 11 (remaining gas: 1039948.715 units remaining) + [ 4 + 5 ] + - location: 14 (remaining gas: 1039948.640 units remaining) + [ 3 + 4 + 5 ] + - location: 17 (remaining gas: 1039948.565 units remaining) + [ 2 + 3 + 4 + 5 ] + - location: 20 (remaining gas: 1039948.490 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 23 (remaining gas: 1039948.399 units remaining) + [ 1 + 1 + 2 + 3 + 4 + 5 ] + - location: 25 (remaining gas: 1039948.324 units remaining) + [ 1 + 1 + 1 + 2 + 3 + 4 + 5 ] + - location: 30 (remaining gas: 1039948.084 units remaining) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 31 (remaining gas: 1039948.009 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039947.964 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 33 (remaining gas: 1039947.864 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039947.819 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 38 (remaining gas: 1039947.727 units remaining) + [ 2 + 1 + 2 + 3 + 4 + 5 ] + - location: 40 (remaining gas: 1039947.652 units remaining) + [ 2 + 2 + 1 + 2 + 3 + 4 + 5 ] + - location: 45 (remaining gas: 1039947.412 units remaining) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 46 (remaining gas: 1039947.337 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039947.292 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 48 (remaining gas: 1039947.192 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039947.147 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 53 (remaining gas: 1039947.054 units remaining) + [ 3 + 1 + 2 + 3 + 4 + 5 ] + - location: 55 (remaining gas: 1039946.979 units remaining) + [ 3 + 3 + 1 + 2 + 3 + 4 + 5 ] + - location: 60 (remaining gas: 1039946.739 units remaining) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 61 (remaining gas: 1039946.664 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039946.619 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 63 (remaining gas: 1039946.519 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039946.474 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 68 (remaining gas: 1039946.379 units remaining) + [ 4 + 1 + 2 + 3 + 4 + 5 ] + - location: 70 (remaining gas: 1039946.304 units remaining) + [ 4 + 4 + 1 + 2 + 3 + 4 + 5 ] + - location: 75 (remaining gas: 1039946.064 units remaining) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 76 (remaining gas: 1039945.989 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039945.944 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 78 (remaining gas: 1039945.844 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039945.799 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 83 (remaining gas: 1039945.703 units remaining) + [ 5 + 1 + 2 + 3 + 4 + 5 ] + - location: 85 (remaining gas: 1039945.628 units remaining) + [ 5 + 5 + 1 + 2 + 3 + 4 + 5 ] + - location: 90 (remaining gas: 1039945.388 units remaining) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 91 (remaining gas: 1039945.313 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039945.268 units remaining) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 93 (remaining gas: 1039945.168 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: -1 (remaining gas: 1039945.123 units remaining) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 98 (remaining gas: 1039944.973 units remaining) + [ ] + - location: 100 (remaining gas: 1039944.898 units remaining) + [ Unit ] + - location: 101 (remaining gas: 1039944.823 units remaining) + [ {} + Unit ] + - location: 103 (remaining gas: 1039944.748 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039944.703 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair -8 2)-(Pair (S.ecc0e72cbb.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair -8 2)-(Pair (S.ecc0e72cbb.out new file mode 100644 index 0000000000000000000000000000000000000000..a349f5052709e6019078e1b6bdc3aa5a63c2d636 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair -8 2)-(Pair (S.ecc0e72cbb.out @@ -0,0 +1,137 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair -8 2)-(Pair (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0)))] + +storage + (Pair (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) +emitted operations + +big_map diff + +trace + - location: 24 (remaining gas: 1039966.445 units remaining) + [ (Pair (Pair -8 2) None None None None) ] + - location: 25 (remaining gas: 1039966.365 units remaining) + [ (Pair -8 2) @parameter ] + - location: 26 (remaining gas: 1039966.285 units remaining) + [ (Pair -8 2) @parameter + (Pair -8 2) @parameter ] + - location: 27 (remaining gas: 1039966.205 units remaining) + [ -8 + 2 + (Pair -8 2) @parameter ] + - location: 28 (remaining gas: 1039966.095 units remaining) + [ 8 + 2 + (Pair -8 2) @parameter ] + - location: 31 (remaining gas: 1039965.910 units remaining) + [ 2 + (Pair -8 2) @parameter ] + - location: 30 (remaining gas: 1039965.865 units remaining) + [ 2 + (Pair -8 2) @parameter ] + - location: 29 (remaining gas: 1039965.865 units remaining) + [ 8 + 2 + (Pair -8 2) @parameter ] + - location: 32 (remaining gas: 1039965.535 units remaining) + [ (Some (Pair 4 0)) + (Pair -8 2) @parameter ] + - location: 33 (remaining gas: 1039965.465 units remaining) + [ (Pair -8 2) @parameter + (Some (Pair 4 0)) ] + - location: 34 (remaining gas: 1039965.385 units remaining) + [ (Pair -8 2) @parameter + (Pair -8 2) @parameter + (Some (Pair 4 0)) ] + - location: 35 (remaining gas: 1039965.305 units remaining) + [ -8 + 2 + (Pair -8 2) @parameter + (Some (Pair 4 0)) ] + - location: 36 (remaining gas: 1039965.195 units remaining) + [ 8 + 2 + (Pair -8 2) @parameter + (Some (Pair 4 0)) ] + - location: 37 (remaining gas: 1039964.865 units remaining) + [ (Some (Pair 4 0)) + (Pair -8 2) @parameter + (Some (Pair 4 0)) ] + - location: 38 (remaining gas: 1039964.795 units remaining) + [ (Pair -8 2) @parameter + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 39 (remaining gas: 1039964.715 units remaining) + [ (Pair -8 2) @parameter + (Pair -8 2) @parameter + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 40 (remaining gas: 1039964.635 units remaining) + [ -8 + 2 + (Pair -8 2) @parameter + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 43 (remaining gas: 1039964.450 units remaining) + [ 2 + (Pair -8 2) @parameter + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 42 (remaining gas: 1039964.405 units remaining) + [ 2 + (Pair -8 2) @parameter + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 41 (remaining gas: 1039964.405 units remaining) + [ -8 + 2 + (Pair -8 2) @parameter + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 44 (remaining gas: 1039964.075 units remaining) + [ (Some (Pair -4 0)) + (Pair -8 2) @parameter + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 45 (remaining gas: 1039964.005 units remaining) + [ (Pair -8 2) @parameter + (Some (Pair -4 0)) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 46 (remaining gas: 1039963.925 units remaining) + [ -8 + 2 + (Some (Pair -4 0)) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 47 (remaining gas: 1039963.595 units remaining) + [ (Some (Pair -4 0)) + (Some (Pair -4 0)) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 52 (remaining gas: 1039963.352 units remaining) + [ (Pair (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 51 (remaining gas: 1039963.307 units remaining) + [ (Pair (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 49 (remaining gas: 1039963.307 units remaining) + [ (Some (Pair -4 0)) + (Some (Pair -4 0)) + (Pair (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 55 (remaining gas: 1039963.157 units remaining) + [ (Pair (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 54 (remaining gas: 1039963.112 units remaining) + [ (Pair (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 53 (remaining gas: 1039963.112 units remaining) + [ (Some (Pair -4 0)) + (Pair (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 56 (remaining gas: 1039963.037 units remaining) + [ (Pair (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: -1 (remaining gas: 1039962.992 units remaining) + [ (Pair (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 57 (remaining gas: 1039962.917 units remaining) + [ {} + (Pair (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 59 (remaining gas: 1039962.842 units remaining) + [ (Pair {} (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: -1 (remaining gas: 1039962.797 units remaining) + [ (Pair {} (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair 10 -3)-(Pair (.3caea50555.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair 10 -3)-(Pair (.3caea50555.out new file mode 100644 index 0000000000000000000000000000000000000000..40e3e919a5a1342115ecb2218056ab9fc96511dc --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair 10 -3)-(Pair (.3caea50555.out @@ -0,0 +1,137 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair 10 -3)-(Pair (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1)))] + +storage + (Pair (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) +emitted operations + +big_map diff + +trace + - location: 24 (remaining gas: 1039966.445 units remaining) + [ (Pair (Pair 10 -3) None None None None) ] + - location: 25 (remaining gas: 1039966.365 units remaining) + [ (Pair 10 -3) @parameter ] + - location: 26 (remaining gas: 1039966.285 units remaining) + [ (Pair 10 -3) @parameter + (Pair 10 -3) @parameter ] + - location: 27 (remaining gas: 1039966.205 units remaining) + [ 10 + -3 + (Pair 10 -3) @parameter ] + - location: 28 (remaining gas: 1039966.095 units remaining) + [ 10 + -3 + (Pair 10 -3) @parameter ] + - location: 31 (remaining gas: 1039965.910 units remaining) + [ 3 + (Pair 10 -3) @parameter ] + - location: 30 (remaining gas: 1039965.865 units remaining) + [ 3 + (Pair 10 -3) @parameter ] + - location: 29 (remaining gas: 1039965.865 units remaining) + [ 10 + 3 + (Pair 10 -3) @parameter ] + - location: 32 (remaining gas: 1039965.535 units remaining) + [ (Some (Pair 3 1)) + (Pair 10 -3) @parameter ] + - location: 33 (remaining gas: 1039965.465 units remaining) + [ (Pair 10 -3) @parameter + (Some (Pair 3 1)) ] + - location: 34 (remaining gas: 1039965.385 units remaining) + [ (Pair 10 -3) @parameter + (Pair 10 -3) @parameter + (Some (Pair 3 1)) ] + - location: 35 (remaining gas: 1039965.305 units remaining) + [ 10 + -3 + (Pair 10 -3) @parameter + (Some (Pair 3 1)) ] + - location: 36 (remaining gas: 1039965.195 units remaining) + [ 10 + -3 + (Pair 10 -3) @parameter + (Some (Pair 3 1)) ] + - location: 37 (remaining gas: 1039964.865 units remaining) + [ (Some (Pair -3 1)) + (Pair 10 -3) @parameter + (Some (Pair 3 1)) ] + - location: 38 (remaining gas: 1039964.795 units remaining) + [ (Pair 10 -3) @parameter + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 39 (remaining gas: 1039964.715 units remaining) + [ (Pair 10 -3) @parameter + (Pair 10 -3) @parameter + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 40 (remaining gas: 1039964.635 units remaining) + [ 10 + -3 + (Pair 10 -3) @parameter + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 43 (remaining gas: 1039964.450 units remaining) + [ 3 + (Pair 10 -3) @parameter + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 42 (remaining gas: 1039964.405 units remaining) + [ 3 + (Pair 10 -3) @parameter + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 41 (remaining gas: 1039964.405 units remaining) + [ 10 + 3 + (Pair 10 -3) @parameter + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 44 (remaining gas: 1039964.075 units remaining) + [ (Some (Pair 3 1)) + (Pair 10 -3) @parameter + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 45 (remaining gas: 1039964.005 units remaining) + [ (Pair 10 -3) @parameter + (Some (Pair 3 1)) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 46 (remaining gas: 1039963.925 units remaining) + [ 10 + -3 + (Some (Pair 3 1)) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 47 (remaining gas: 1039963.595 units remaining) + [ (Some (Pair -3 1)) + (Some (Pair 3 1)) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 52 (remaining gas: 1039963.352 units remaining) + [ (Pair (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 51 (remaining gas: 1039963.307 units remaining) + [ (Pair (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 49 (remaining gas: 1039963.307 units remaining) + [ (Some (Pair -3 1)) + (Some (Pair 3 1)) + (Pair (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 55 (remaining gas: 1039963.157 units remaining) + [ (Pair (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 54 (remaining gas: 1039963.112 units remaining) + [ (Pair (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 53 (remaining gas: 1039963.112 units remaining) + [ (Some (Pair -3 1)) + (Pair (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 56 (remaining gas: 1039963.037 units remaining) + [ (Pair (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: -1 (remaining gas: 1039962.992 units remaining) + [ (Pair (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 57 (remaining gas: 1039962.917 units remaining) + [ {} + (Pair (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 59 (remaining gas: 1039962.842 units remaining) + [ (Pair {} (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: -1 (remaining gas: 1039962.797 units remaining) + [ (Pair {} (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair 10 0)-(Pair No.f9448c04fb.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair 10 0)-(Pair No.f9448c04fb.out new file mode 100644 index 0000000000000000000000000000000000000000..4403b103773e45bf3f639513a700dd3a5ab8671b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair 10 0)-(Pair No.f9448c04fb.out @@ -0,0 +1,137 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv.tz-(Pair None None None None)-(Pair 10 0)-(Pair None None None None)] + +storage + (Pair None None None None) +emitted operations + +big_map diff + +trace + - location: 24 (remaining gas: 1039966.445 units remaining) + [ (Pair (Pair 10 0) None None None None) ] + - location: 25 (remaining gas: 1039966.365 units remaining) + [ (Pair 10 0) @parameter ] + - location: 26 (remaining gas: 1039966.285 units remaining) + [ (Pair 10 0) @parameter + (Pair 10 0) @parameter ] + - location: 27 (remaining gas: 1039966.205 units remaining) + [ 10 + 0 + (Pair 10 0) @parameter ] + - location: 28 (remaining gas: 1039966.095 units remaining) + [ 10 + 0 + (Pair 10 0) @parameter ] + - location: 31 (remaining gas: 1039965.910 units remaining) + [ 0 + (Pair 10 0) @parameter ] + - location: 30 (remaining gas: 1039965.865 units remaining) + [ 0 + (Pair 10 0) @parameter ] + - location: 29 (remaining gas: 1039965.865 units remaining) + [ 10 + 0 + (Pair 10 0) @parameter ] + - location: 32 (remaining gas: 1039965.535 units remaining) + [ None + (Pair 10 0) @parameter ] + - location: 33 (remaining gas: 1039965.465 units remaining) + [ (Pair 10 0) @parameter + None ] + - location: 34 (remaining gas: 1039965.385 units remaining) + [ (Pair 10 0) @parameter + (Pair 10 0) @parameter + None ] + - location: 35 (remaining gas: 1039965.305 units remaining) + [ 10 + 0 + (Pair 10 0) @parameter + None ] + - location: 36 (remaining gas: 1039965.195 units remaining) + [ 10 + 0 + (Pair 10 0) @parameter + None ] + - location: 37 (remaining gas: 1039964.865 units remaining) + [ None + (Pair 10 0) @parameter + None ] + - location: 38 (remaining gas: 1039964.795 units remaining) + [ (Pair 10 0) @parameter + None + None ] + - location: 39 (remaining gas: 1039964.715 units remaining) + [ (Pair 10 0) @parameter + (Pair 10 0) @parameter + None + None ] + - location: 40 (remaining gas: 1039964.635 units remaining) + [ 10 + 0 + (Pair 10 0) @parameter + None + None ] + - location: 43 (remaining gas: 1039964.450 units remaining) + [ 0 + (Pair 10 0) @parameter + None + None ] + - location: 42 (remaining gas: 1039964.405 units remaining) + [ 0 + (Pair 10 0) @parameter + None + None ] + - location: 41 (remaining gas: 1039964.405 units remaining) + [ 10 + 0 + (Pair 10 0) @parameter + None + None ] + - location: 44 (remaining gas: 1039964.075 units remaining) + [ None + (Pair 10 0) @parameter + None + None ] + - location: 45 (remaining gas: 1039964.005 units remaining) + [ (Pair 10 0) @parameter + None + None + None ] + - location: 46 (remaining gas: 1039963.925 units remaining) + [ 10 + 0 + None + None + None ] + - location: 47 (remaining gas: 1039963.595 units remaining) + [ None + None + None + None ] + - location: 52 (remaining gas: 1039963.352 units remaining) + [ (Pair None None) ] + - location: 51 (remaining gas: 1039963.307 units remaining) + [ (Pair None None) ] + - location: 49 (remaining gas: 1039963.307 units remaining) + [ None + None + (Pair None None) ] + - location: 55 (remaining gas: 1039963.157 units remaining) + [ (Pair None None None) ] + - location: 54 (remaining gas: 1039963.112 units remaining) + [ (Pair None None None) ] + - location: 53 (remaining gas: 1039963.112 units remaining) + [ None + (Pair None None None) ] + - location: 56 (remaining gas: 1039963.037 units remaining) + [ (Pair None None None None) ] + - location: -1 (remaining gas: 1039962.992 units remaining) + [ (Pair None None None None) ] + - location: 57 (remaining gas: 1039962.917 units remaining) + [ {} + (Pair None None None None) ] + - location: 59 (remaining gas: 1039962.842 units remaining) + [ (Pair {} None None None None) ] + - location: -1 (remaining gas: 1039962.797 units remaining) + [ (Pair {} None None None None) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 0))-(Left None)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 0))-(Left None)].out new file mode 100644 index 0000000000000000000000000000000000000000..93589e6d0f697267e3b3d5f04c2c74de70c0a74a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 0))-(Left None)].out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 0))-(Left None)] + +storage + (Left None) +emitted operations + +big_map diff + +trace + - location: 18 (remaining gas: 1039982.170 units remaining) + [ (Pair (Pair 10 (Left 0)) (Left None)) ] + - location: 19 (remaining gas: 1039982.090 units remaining) + [ (Pair 10 (Left 0)) @parameter ] + - location: 20 (remaining gas: 1039982.010 units remaining) + [ 10 + (Left 0) ] + - location: 21 (remaining gas: 1039981.940 units remaining) + [ (Left 0) + 10 ] + - location: 24 (remaining gas: 1039981.810 units remaining) + [ 10 + 0 ] + - location: 25 (remaining gas: 1039981.580 units remaining) + [ None ] + - location: 26 (remaining gas: 1039981.505 units remaining) + [ (Left None) ] + - location: -1 (remaining gas: 1039981.460 units remaining) + [ (Left None) ] + - location: 39 (remaining gas: 1039981.385 units remaining) + [ {} + (Left None) ] + - location: 41 (remaining gas: 1039981.310 units remaining) + [ (Pair {} (Left None)) ] + - location: -1 (remaining gas: 1039981.265 units remaining) + [ (Pair {} (Left None)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 10))-(Left (So.f782cc1dec.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 10))-(Left (So.f782cc1dec.out new file mode 100644 index 0000000000000000000000000000000000000000..b1c8d3f8e85f7b4b1d18df675fc6f28501f3a5ee --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 10))-(Left (So.f782cc1dec.out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 10))-(Left (Some (Pair 1 0)))] + +storage + (Left (Some (Pair 1 0))) +emitted operations + +big_map diff + +trace + - location: 18 (remaining gas: 1039982.170 units remaining) + [ (Pair (Pair 10 (Left 10)) (Left None)) ] + - location: 19 (remaining gas: 1039982.090 units remaining) + [ (Pair 10 (Left 10)) @parameter ] + - location: 20 (remaining gas: 1039982.010 units remaining) + [ 10 + (Left 10) ] + - location: 21 (remaining gas: 1039981.940 units remaining) + [ (Left 10) + 10 ] + - location: 24 (remaining gas: 1039981.810 units remaining) + [ 10 + 10 ] + - location: 25 (remaining gas: 1039981.580 units remaining) + [ (Some (Pair 1 0)) ] + - location: 26 (remaining gas: 1039981.505 units remaining) + [ (Left (Some (Pair 1 0))) ] + - location: -1 (remaining gas: 1039981.460 units remaining) + [ (Left (Some (Pair 1 0))) ] + - location: 39 (remaining gas: 1039981.385 units remaining) + [ {} + (Left (Some (Pair 1 0))) ] + - location: 41 (remaining gas: 1039981.310 units remaining) + [ (Pair {} (Left (Some (Pair 1 0)))) ] + - location: -1 (remaining gas: 1039981.265 units remaining) + [ (Pair {} (Left (Some (Pair 1 0)))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 3))-(Left (Som.016b4db96c.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 3))-(Left (Som.016b4db96c.out new file mode 100644 index 0000000000000000000000000000000000000000..216b9c470b91dce95adcbfb6846cc81ee163b5bb --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 3))-(Left (Som.016b4db96c.out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Left 3))-(Left (Some (Pair 3 1)))] + +storage + (Left (Some (Pair 3 1))) +emitted operations + +big_map diff + +trace + - location: 18 (remaining gas: 1039982.170 units remaining) + [ (Pair (Pair 10 (Left 3)) (Left None)) ] + - location: 19 (remaining gas: 1039982.090 units remaining) + [ (Pair 10 (Left 3)) @parameter ] + - location: 20 (remaining gas: 1039982.010 units remaining) + [ 10 + (Left 3) ] + - location: 21 (remaining gas: 1039981.940 units remaining) + [ (Left 3) + 10 ] + - location: 24 (remaining gas: 1039981.810 units remaining) + [ 10 + 3 ] + - location: 25 (remaining gas: 1039981.580 units remaining) + [ (Some (Pair 3 1)) ] + - location: 26 (remaining gas: 1039981.505 units remaining) + [ (Left (Some (Pair 3 1))) ] + - location: -1 (remaining gas: 1039981.460 units remaining) + [ (Left (Some (Pair 3 1))) ] + - location: 39 (remaining gas: 1039981.385 units remaining) + [ {} + (Left (Some (Pair 3 1))) ] + - location: 41 (remaining gas: 1039981.310 units remaining) + [ (Pair {} (Left (Some (Pair 3 1)))) ] + - location: -1 (remaining gas: 1039981.265 units remaining) + [ (Pair {} (Left (Some (Pair 3 1)))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 0))-(Right None)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 0))-(Right None)].out new file mode 100644 index 0000000000000000000000000000000000000000..e48f18cb91c206971b2fb4b1af0d0960b4849c39 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 0))-(Right None)].out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 0))-(Right None)] + +storage + (Right None) +emitted operations + +big_map diff + +trace + - location: 18 (remaining gas: 1039982.170 units remaining) + [ (Pair (Pair 10 (Right 0)) (Left None)) ] + - location: 19 (remaining gas: 1039982.090 units remaining) + [ (Pair 10 (Right 0)) @parameter ] + - location: 20 (remaining gas: 1039982.010 units remaining) + [ 10 + (Right 0) ] + - location: 21 (remaining gas: 1039981.940 units remaining) + [ (Right 0) + 10 ] + - location: 32 (remaining gas: 1039981.810 units remaining) + [ 10 + 0 ] + - location: 33 (remaining gas: 1039981.480 units remaining) + [ None ] + - location: 34 (remaining gas: 1039981.405 units remaining) + [ (Right None) ] + - location: -1 (remaining gas: 1039981.360 units remaining) + [ (Right None) ] + - location: 39 (remaining gas: 1039981.285 units remaining) + [ {} + (Right None) ] + - location: 41 (remaining gas: 1039981.210 units remaining) + [ (Pair {} (Right None)) ] + - location: -1 (remaining gas: 1039981.165 units remaining) + [ (Pair {} (Right None)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 10))-(Right (.e705a30e07.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 10))-(Right (.e705a30e07.out new file mode 100644 index 0000000000000000000000000000000000000000..4fff3551e082844e59cacc1d108edb66d644d71e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 10))-(Right (.e705a30e07.out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 10))-(Right (Some (Pair 1 0)))] + +storage + (Right (Some (Pair 1 0))) +emitted operations + +big_map diff + +trace + - location: 18 (remaining gas: 1039982.170 units remaining) + [ (Pair (Pair 10 (Right 10)) (Left None)) ] + - location: 19 (remaining gas: 1039982.090 units remaining) + [ (Pair 10 (Right 10)) @parameter ] + - location: 20 (remaining gas: 1039982.010 units remaining) + [ 10 + (Right 10) ] + - location: 21 (remaining gas: 1039981.940 units remaining) + [ (Right 10) + 10 ] + - location: 32 (remaining gas: 1039981.810 units remaining) + [ 10 + 10 ] + - location: 33 (remaining gas: 1039981.480 units remaining) + [ (Some (Pair 1 0)) ] + - location: 34 (remaining gas: 1039981.405 units remaining) + [ (Right (Some (Pair 1 0))) ] + - location: -1 (remaining gas: 1039981.360 units remaining) + [ (Right (Some (Pair 1 0))) ] + - location: 39 (remaining gas: 1039981.285 units remaining) + [ {} + (Right (Some (Pair 1 0))) ] + - location: 41 (remaining gas: 1039981.210 units remaining) + [ (Pair {} (Right (Some (Pair 1 0)))) ] + - location: -1 (remaining gas: 1039981.165 units remaining) + [ (Pair {} (Right (Some (Pair 1 0)))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 3))-(Right (S.44485eda6a.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 3))-(Right (S.44485eda6a.out new file mode 100644 index 0000000000000000000000000000000000000000..dc567475a15e745a07cd64e4414e95952c516e2d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 3))-(Right (S.44485eda6a.out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 10 (Right 3))-(Right (Some (Pair 3 1)))] + +storage + (Right (Some (Pair 3 1))) +emitted operations + +big_map diff + +trace + - location: 18 (remaining gas: 1039982.170 units remaining) + [ (Pair (Pair 10 (Right 3)) (Left None)) ] + - location: 19 (remaining gas: 1039982.090 units remaining) + [ (Pair 10 (Right 3)) @parameter ] + - location: 20 (remaining gas: 1039982.010 units remaining) + [ 10 + (Right 3) ] + - location: 21 (remaining gas: 1039981.940 units remaining) + [ (Right 3) + 10 ] + - location: 32 (remaining gas: 1039981.810 units remaining) + [ 10 + 3 ] + - location: 33 (remaining gas: 1039981.480 units remaining) + [ (Some (Pair 3 1)) ] + - location: 34 (remaining gas: 1039981.405 units remaining) + [ (Right (Some (Pair 3 1))) ] + - location: -1 (remaining gas: 1039981.360 units remaining) + [ (Right (Some (Pair 3 1))) ] + - location: 39 (remaining gas: 1039981.285 units remaining) + [ {} + (Right (Some (Pair 3 1))) ] + - location: 41 (remaining gas: 1039981.210 units remaining) + [ (Pair {} (Right (Some (Pair 3 1)))) ] + - location: -1 (remaining gas: 1039981.165 units remaining) + [ (Pair {} (Right (Some (Pair 3 1)))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 5 (Right 10))-(Right (S.8ab987af15.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 5 (Right 10))-(Right (S.8ab987af15.out new file mode 100644 index 0000000000000000000000000000000000000000..19e98c838656af1ae96b3f8945aa018109417f91 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 5 (Right 10))-(Right (S.8ab987af15.out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ediv_mutez.tz-(Left None)-(Pair 5 (Right 10))-(Right (Some (Pair 0 5)))] + +storage + (Right (Some (Pair 0 5))) +emitted operations + +big_map diff + +trace + - location: 18 (remaining gas: 1039982.170 units remaining) + [ (Pair (Pair 5 (Right 10)) (Left None)) ] + - location: 19 (remaining gas: 1039982.090 units remaining) + [ (Pair 5 (Right 10)) @parameter ] + - location: 20 (remaining gas: 1039982.010 units remaining) + [ 5 + (Right 10) ] + - location: 21 (remaining gas: 1039981.940 units remaining) + [ (Right 10) + 5 ] + - location: 32 (remaining gas: 1039981.810 units remaining) + [ 5 + 10 ] + - location: 33 (remaining gas: 1039981.480 units remaining) + [ (Some (Pair 0 5)) ] + - location: 34 (remaining gas: 1039981.405 units remaining) + [ (Right (Some (Pair 0 5))) ] + - location: -1 (remaining gas: 1039981.360 units remaining) + [ (Right (Some (Pair 0 5))) ] + - location: 39 (remaining gas: 1039981.285 units remaining) + [ {} + (Right (Some (Pair 0 5))) ] + - location: 41 (remaining gas: 1039981.210 units remaining) + [ (Pair {} (Right (Some (Pair 0 5)))) ] + - location: -1 (remaining gas: 1039981.165 units remaining) + [ (Pair {} (Right (Some (Pair 0 5)))) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[empty_map.tz-{}-Unit-{ Elt \"hello\" \"world\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[empty_map.tz-{}-Unit-{ Elt \"hello\" \"world\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..d2863c6387e9ccc5bf2bc32148986e7e600f566d --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[empty_map.tz-{}-Unit-{ Elt \"hello\" \"world\" }].out" @@ -0,0 +1,35 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[empty_map.tz-{}-Unit-{ Elt "hello" "world" }] + +storage + { Elt "hello" "world" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039989.592 units remaining) + [ (Pair Unit {}) ] + - location: 9 (remaining gas: 1039989.517 units remaining) + [ ] + - location: 10 (remaining gas: 1039989.287 units remaining) + [ {} ] + - location: 13 (remaining gas: 1039989.212 units remaining) + [ "world" + {} ] + - location: 16 (remaining gas: 1039989.137 units remaining) + [ (Some "world") + {} ] + - location: 17 (remaining gas: 1039989.062 units remaining) + [ "hello" + (Some "world") + {} ] + - location: 20 (remaining gas: 1039988.952 units remaining) + [ { Elt "hello" "world" } ] + - location: 21 (remaining gas: 1039988.877 units remaining) + [ {} + { Elt "hello" "world" } ] + - location: 23 (remaining gas: 1039988.802 units remaining) + [ (Pair {} { Elt "hello" "world" }) ] + - location: -1 (remaining gas: 1039988.757 units remaining) + [ (Pair {} { Elt "hello" "world" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[exec_concat.tz-\"?\"-\"\"-\"_abc\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[exec_concat.tz-\"?\"-\"\"-\"_abc\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..d68503b8c6c85b88a8348363d28d9516cfc77b71 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[exec_concat.tz-\"?\"-\"\"-\"_abc\"].out" @@ -0,0 +1,54 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[exec_concat.tz-"?"-""-"_abc"] + +storage + "_abc" +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039986.458 units remaining) + [ (Pair "" "?") ] + - location: 7 (remaining gas: 1039986.378 units remaining) + [ "" @parameter ] + - location: 8 (remaining gas: 1039986.303 units remaining) + [ { PUSH string "_abc" ; NIL string ; SWAP ; CONS ; SWAP ; CONS ; CONCAT } + "" @parameter ] + - location: 22 (remaining gas: 1039986.233 units remaining) + [ "" @parameter + { PUSH string "_abc" ; NIL string ; SWAP ; CONS ; SWAP ; CONS ; CONCAT } ] + - location: 11 (remaining gas: 1039986.103 units remaining) + [ "" @arg ] + - location: 12 (remaining gas: 1039986.028 units remaining) + [ "_abc" + "" @arg ] + - location: 15 (remaining gas: 1039985.953 units remaining) + [ {} + "_abc" + "" @arg ] + - location: 17 (remaining gas: 1039985.883 units remaining) + [ "_abc" + {} + "" @arg ] + - location: 18 (remaining gas: 1039985.803 units remaining) + [ { "_abc" } + "" @arg ] + - location: 19 (remaining gas: 1039985.733 units remaining) + [ "" @arg + { "_abc" } ] + - location: 20 (remaining gas: 1039985.653 units remaining) + [ { "" ; "_abc" } ] + - location: 21 (remaining gas: 1039985.503 units remaining) + [ "_abc" ] + - location: -1 (remaining gas: 1039985.458 units remaining) + [ "_abc" ] + - location: 23 (remaining gas: 1039985.458 units remaining) + [ "_abc" ] + - location: 24 (remaining gas: 1039985.383 units remaining) + [ {} + "_abc" ] + - location: 26 (remaining gas: 1039985.308 units remaining) + [ (Pair {} "_abc") ] + - location: -1 (remaining gas: 1039985.263 units remaining) + [ (Pair {} "_abc") ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[exec_concat.tz-\"?\"-\"test\"-\"test_abc\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[exec_concat.tz-\"?\"-\"test\"-\"test_abc\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..077fd908e003c66621736fde258f540494685234 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[exec_concat.tz-\"?\"-\"test\"-\"test_abc\"].out" @@ -0,0 +1,54 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[exec_concat.tz-"?"-"test"-"test_abc"] + +storage + "test_abc" +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039986.418 units remaining) + [ (Pair "test" "?") ] + - location: 7 (remaining gas: 1039986.338 units remaining) + [ "test" @parameter ] + - location: 8 (remaining gas: 1039986.263 units remaining) + [ { PUSH string "_abc" ; NIL string ; SWAP ; CONS ; SWAP ; CONS ; CONCAT } + "test" @parameter ] + - location: 22 (remaining gas: 1039986.193 units remaining) + [ "test" @parameter + { PUSH string "_abc" ; NIL string ; SWAP ; CONS ; SWAP ; CONS ; CONCAT } ] + - location: 11 (remaining gas: 1039986.063 units remaining) + [ "test" @arg ] + - location: 12 (remaining gas: 1039985.988 units remaining) + [ "_abc" + "test" @arg ] + - location: 15 (remaining gas: 1039985.913 units remaining) + [ {} + "_abc" + "test" @arg ] + - location: 17 (remaining gas: 1039985.843 units remaining) + [ "_abc" + {} + "test" @arg ] + - location: 18 (remaining gas: 1039985.763 units remaining) + [ { "_abc" } + "test" @arg ] + - location: 19 (remaining gas: 1039985.693 units remaining) + [ "test" @arg + { "_abc" } ] + - location: 20 (remaining gas: 1039985.613 units remaining) + [ { "test" ; "_abc" } ] + - location: 21 (remaining gas: 1039985.463 units remaining) + [ "test_abc" ] + - location: -1 (remaining gas: 1039985.418 units remaining) + [ "test_abc" ] + - location: 23 (remaining gas: 1039985.418 units remaining) + [ "test_abc" ] + - location: 24 (remaining gas: 1039985.343 units remaining) + [ {} + "test_abc" ] + - location: 26 (remaining gas: 1039985.268 units remaining) + [ (Pair {} "test_abc") ] + - location: -1 (remaining gas: 1039985.223 units remaining) + [ (Pair {} "test_abc") ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[first.tz-111-{ 1 ; 2 ; 3 ; 4 }-1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[first.tz-111-{ 1 ; 2 ; 3 ; 4 }-1].out new file mode 100644 index 0000000000000000000000000000000000000000..13137f6c900d2a0c3a99d23e10eae4ed09a35864 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[first.tz-111-{ 1 ; 2 ; 3 ; 4 }-1].out @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[first.tz-111-{ 1 ; 2 ; 3 ; 4 }-1] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039990.235 units remaining) + [ (Pair { 1 ; 2 ; 3 ; 4 } 111) ] + - location: 8 (remaining gas: 1039990.155 units remaining) + [ { 1 ; 2 ; 3 ; 4 } @parameter ] + - location: 13 (remaining gas: 1039989.945 units remaining) + [ ] + - location: 12 (remaining gas: 1039989.900 units remaining) + [ ] + - location: 11 (remaining gas: 1039989.900 units remaining) + [ 1 @parameter.hd ] + - location: 10 (remaining gas: 1039989.855 units remaining) + [ 1 @parameter.hd ] + - location: 18 (remaining gas: 1039989.780 units remaining) + [ {} + 1 @parameter.hd ] + - location: 20 (remaining gas: 1039989.705 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039989.660 units remaining) + [ (Pair {} 1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[first.tz-111-{ 4 }-4].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[first.tz-111-{ 4 }-4].out new file mode 100644 index 0000000000000000000000000000000000000000..27ba6e37251d1e125e2b7059f249a918a7b7db9b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[first.tz-111-{ 4 }-4].out @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[first.tz-111-{ 4 }-4] + +storage + 4 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039990.955 units remaining) + [ (Pair { 4 } 111) ] + - location: 8 (remaining gas: 1039990.875 units remaining) + [ { 4 } @parameter ] + - location: 13 (remaining gas: 1039990.665 units remaining) + [ ] + - location: 12 (remaining gas: 1039990.620 units remaining) + [ ] + - location: 11 (remaining gas: 1039990.620 units remaining) + [ 4 @parameter.hd ] + - location: 10 (remaining gas: 1039990.575 units remaining) + [ 4 @parameter.hd ] + - location: 18 (remaining gas: 1039990.500 units remaining) + [ {} + 4 @parameter.hd ] + - location: 20 (remaining gas: 1039990.425 units remaining) + [ (Pair {} 4) ] + - location: -1 (remaining gas: 1039990.380 units remaining) + [ (Pair {} 4) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 4) {})-\"hello\"-(Pair .161d86cef6.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 4) {})-\"hello\"-(Pair .161d86cef6.out" new file mode 100644 index 0000000000000000000000000000000000000000..95a051c2bdf65a408f89329c3dffb9a849f8b4d3 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 4) {})-\"hello\"-(Pair .161d86cef6.out" @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 4) {})-"hello"-(Pair None { Elt "hello" 4 })] + +storage + (Pair None { Elt "hello" 4 }) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039989.571 units remaining) + [ (Pair "hello" (Some 4) {}) ] + - location: 13 (remaining gas: 1039989.461 units remaining) + [ "hello" @parameter + (Pair (Some 4) {}) @storage ] + - location: 16 (remaining gas: 1039989.306 units remaining) + [ (Some 4) + {} ] + - location: 15 (remaining gas: 1039989.261 units remaining) + [ (Some 4) + {} ] + - location: 14 (remaining gas: 1039989.261 units remaining) + [ "hello" @parameter + (Some 4) + {} ] + - location: -1 (remaining gas: 1039989.216 units remaining) + [ "hello" @parameter + (Some 4) + {} ] + - location: 17 (remaining gas: 1039989.026 units remaining) + [ None + { Elt "hello" 4 } ] + - location: 18 (remaining gas: 1039988.951 units remaining) + [ (Pair None { Elt "hello" 4 }) ] + - location: 19 (remaining gas: 1039988.876 units remaining) + [ {} + (Pair None { Elt "hello" 4 }) ] + - location: 21 (remaining gas: 1039988.801 units remaining) + [ (Pair {} None { Elt "hello" 4 }) ] + - location: -1 (remaining gas: 1039988.756 units remaining) + [ (Pair {} None { Elt "hello" 4 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 5) { Elt \"hello\" 4 }).684ab7e326.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 5) { Elt \"hello\" 4 }).684ab7e326.out" new file mode 100644 index 0000000000000000000000000000000000000000..1b0f07b3b060aa2e1c47bcd6efb07bfc9785e497 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 5) { Elt \"hello\" 4 }).684ab7e326.out" @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 5) { Elt "hello" 4 })-"hi"-(Pair None { Elt "hello" 4 ; Elt "hi" 5 })] + +storage + (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039988.977 units remaining) + [ (Pair "hi" (Some 5) { Elt "hello" 4 }) ] + - location: 13 (remaining gas: 1039988.867 units remaining) + [ "hi" @parameter + (Pair (Some 5) { Elt "hello" 4 }) @storage ] + - location: 16 (remaining gas: 1039988.712 units remaining) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 15 (remaining gas: 1039988.667 units remaining) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 14 (remaining gas: 1039988.667 units remaining) + [ "hi" @parameter + (Some 5) + { Elt "hello" 4 } ] + - location: -1 (remaining gas: 1039988.622 units remaining) + [ "hi" @parameter + (Some 5) + { Elt "hello" 4 } ] + - location: 17 (remaining gas: 1039988.432 units remaining) + [ None + { Elt "hello" 4 ; Elt "hi" 5 } ] + - location: 18 (remaining gas: 1039988.357 units remaining) + [ (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: 19 (remaining gas: 1039988.282 units remaining) + [ {} + (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: 21 (remaining gas: 1039988.207 units remaining) + [ (Pair {} None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: -1 (remaining gas: 1039988.162 units remaining) + [ (Pair {} None { Elt "hello" 4 ; Elt "hi" 5 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 5) { Elt \"hello\" 4 }).d49817fb83.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 5) { Elt \"hello\" 4 }).d49817fb83.out" new file mode 100644 index 0000000000000000000000000000000000000000..fd5a469d7e9dbd5a355edcdfae2bff8afcdb87ea --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 5) { Elt \"hello\" 4 }).d49817fb83.out" @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair (Some 5) { Elt "hello" 4 })-"hello"-(Pair (Some 4) { Elt "hello" 5 })] + +storage + (Pair (Some 4) { Elt "hello" 5 }) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039988.947 units remaining) + [ (Pair "hello" (Some 5) { Elt "hello" 4 }) ] + - location: 13 (remaining gas: 1039988.837 units remaining) + [ "hello" @parameter + (Pair (Some 5) { Elt "hello" 4 }) @storage ] + - location: 16 (remaining gas: 1039988.682 units remaining) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 15 (remaining gas: 1039988.637 units remaining) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 14 (remaining gas: 1039988.637 units remaining) + [ "hello" @parameter + (Some 5) + { Elt "hello" 4 } ] + - location: -1 (remaining gas: 1039988.592 units remaining) + [ "hello" @parameter + (Some 5) + { Elt "hello" 4 } ] + - location: 17 (remaining gas: 1039988.402 units remaining) + [ (Some 4) + { Elt "hello" 5 } ] + - location: 18 (remaining gas: 1039988.327 units remaining) + [ (Pair (Some 4) { Elt "hello" 5 }) ] + - location: 19 (remaining gas: 1039988.252 units remaining) + [ {} + (Pair (Some 4) { Elt "hello" 5 }) ] + - location: 21 (remaining gas: 1039988.177 units remaining) + [ (Pair {} (Some 4) { Elt "hello" 5 }) ] + - location: -1 (remaining gas: 1039988.132 units remaining) + [ (Pair {} (Some 4) { Elt "hello" 5 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt \"1\" 1 ; .6900b1da14.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt \"1\" 1 ; .6900b1da14.out" new file mode 100644 index 0000000000000000000000000000000000000000..820561bf141f2844bbb69bc0d641cdb7dfa2f5ac --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt \"1\" 1 ; .6900b1da14.out" @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt "1" 1 ; Elt "2" 2 })-"1"-(Pair (Some 1) { Elt "2" 2 })1] + +storage + (Pair (Some 1) { Elt "2" 2 }) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039988.563 units remaining) + [ (Pair "1" None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 13 (remaining gas: 1039988.453 units remaining) + [ "1" @parameter + (Pair None { Elt "1" 1 ; Elt "2" 2 }) @storage ] + - location: 16 (remaining gas: 1039988.298 units remaining) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 15 (remaining gas: 1039988.253 units remaining) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 14 (remaining gas: 1039988.253 units remaining) + [ "1" @parameter + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: -1 (remaining gas: 1039988.208 units remaining) + [ "1" @parameter + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 17 (remaining gas: 1039988.018 units remaining) + [ (Some 1) + { Elt "2" 2 } ] + - location: 18 (remaining gas: 1039987.943 units remaining) + [ (Pair (Some 1) { Elt "2" 2 }) ] + - location: 19 (remaining gas: 1039987.868 units remaining) + [ {} + (Pair (Some 1) { Elt "2" 2 }) ] + - location: 21 (remaining gas: 1039987.793 units remaining) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + - location: -1 (remaining gas: 1039987.748 units remaining) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt \"1\" 1 ; .bca0ede8be.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt \"1\" 1 ; .bca0ede8be.out" new file mode 100644 index 0000000000000000000000000000000000000000..e33d88275dd1b173d15b360f88b140303af86a42 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt \"1\" 1 ; .bca0ede8be.out" @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt "1" 1 ; Elt "2" 2 })-"1"-(Pair (Some 1) { Elt "2" 2 })0] + +storage + (Pair (Some 1) { Elt "2" 2 }) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039988.563 units remaining) + [ (Pair "1" None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 13 (remaining gas: 1039988.453 units remaining) + [ "1" @parameter + (Pair None { Elt "1" 1 ; Elt "2" 2 }) @storage ] + - location: 16 (remaining gas: 1039988.298 units remaining) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 15 (remaining gas: 1039988.253 units remaining) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 14 (remaining gas: 1039988.253 units remaining) + [ "1" @parameter + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: -1 (remaining gas: 1039988.208 units remaining) + [ "1" @parameter + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 17 (remaining gas: 1039988.018 units remaining) + [ (Some 1) + { Elt "2" 2 } ] + - location: 18 (remaining gas: 1039987.943 units remaining) + [ (Pair (Some 1) { Elt "2" 2 }) ] + - location: 19 (remaining gas: 1039987.868 units remaining) + [ {} + (Pair (Some 1) { Elt "2" 2 }) ] + - location: 21 (remaining gas: 1039987.793 units remaining) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + - location: -1 (remaining gas: 1039987.748 units remaining) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt \"hello\" 4 })-\"he.c1b4e1d6dc.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt \"hello\" 4 })-\"he.c1b4e1d6dc.out" new file mode 100644 index 0000000000000000000000000000000000000000..a37db37064adccb07ad9baeae595865d53dab6a2 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt \"hello\" 4 })-\"he.c1b4e1d6dc.out" @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None { Elt "hello" 4 })-"hello"-(Pair (Some 4) {})] + +storage + (Pair (Some 4) {}) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039989.187 units remaining) + [ (Pair "hello" None { Elt "hello" 4 }) ] + - location: 13 (remaining gas: 1039989.077 units remaining) + [ "hello" @parameter + (Pair None { Elt "hello" 4 }) @storage ] + - location: 16 (remaining gas: 1039988.922 units remaining) + [ None + { Elt "hello" 4 } ] + - location: 15 (remaining gas: 1039988.877 units remaining) + [ None + { Elt "hello" 4 } ] + - location: 14 (remaining gas: 1039988.877 units remaining) + [ "hello" @parameter + None + { Elt "hello" 4 } ] + - location: -1 (remaining gas: 1039988.832 units remaining) + [ "hello" @parameter + None + { Elt "hello" 4 } ] + - location: 17 (remaining gas: 1039988.642 units remaining) + [ (Some 4) + {} ] + - location: 18 (remaining gas: 1039988.567 units remaining) + [ (Pair (Some 4) {}) ] + - location: 19 (remaining gas: 1039988.492 units remaining) + [ {} + (Pair (Some 4) {}) ] + - location: 21 (remaining gas: 1039988.417 units remaining) + [ (Pair {} (Some 4) {}) ] + - location: -1 (remaining gas: 1039988.372 units remaining) + [ (Pair {} (Some 4) {}) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None {})-\"hello\"-(Pair None {})].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None {})-\"hello\"-(Pair None {})].out" new file mode 100644 index 0000000000000000000000000000000000000000..8cef572b477aac2aa46c99f60ae7f71c7b391f83 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None {})-\"hello\"-(Pair None {})].out" @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_and_update_map.tz-(Pair None {})-"hello"-(Pair None {})] + +storage + (Pair None {}) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039989.811 units remaining) + [ (Pair "hello" None {}) ] + - location: 13 (remaining gas: 1039989.701 units remaining) + [ "hello" @parameter + (Pair None {}) @storage ] + - location: 16 (remaining gas: 1039989.546 units remaining) + [ None + {} ] + - location: 15 (remaining gas: 1039989.501 units remaining) + [ None + {} ] + - location: 14 (remaining gas: 1039989.501 units remaining) + [ "hello" @parameter + None + {} ] + - location: -1 (remaining gas: 1039989.456 units remaining) + [ "hello" @parameter + None + {} ] + - location: 17 (remaining gas: 1039989.266 units remaining) + [ None + {} ] + - location: 18 (remaining gas: 1039989.191 units remaining) + [ (Pair None {}) ] + - location: 19 (remaining gas: 1039989.116 units remaining) + [ {} + (Pair None {}) ] + - location: 21 (remaining gas: 1039989.041 units remaining) + [ (Pair {} None {}) ] + - location: -1 (remaining gas: 1039988.996 units remaining) + [ (Pair {} None {}) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt \"1\" \"one\" ; .bc4127094e.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt \"1\" \"one\" ; .bc4127094e.out" new file mode 100644 index 0000000000000000000000000000000000000000..7b4d9e106c295c2a6949d80338a1120f7657c33b --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt \"1\" \"one\" ; .bc4127094e.out" @@ -0,0 +1,46 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt "1" "one" ; Elt "2" "two" })-"1"-(Pair (Some "one") { Elt "1" "one" ; Elt "2" "two" })] + +storage + (Pair (Some "one") { Elt "1" "one" ; Elt "2" "two" }) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039984.195 units remaining) + [ (Pair "1" None { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 12 (remaining gas: 1039984.115 units remaining) + [ (Pair "1" None { Elt "1" "one" ; Elt "2" "two" }) + (Pair "1" None { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 13 (remaining gas: 1039984.035 units remaining) + [ "1" @parameter + (Pair "1" None { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 17 (remaining gas: 1039983.850 units remaining) + [ (Pair None { Elt "1" "one" ; Elt "2" "two" }) @storage ] + - location: 18 (remaining gas: 1039983.770 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } ] + - location: -1 (remaining gas: 1039983.725 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } ] + - location: 19 (remaining gas: 1039983.645 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: -1 (remaining gas: 1039983.600 units remaining) + [ { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 14 (remaining gas: 1039983.600 units remaining) + [ "1" @parameter + { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 20 (remaining gas: 1039983.490 units remaining) + [ (Some "one") + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 21 (remaining gas: 1039983.415 units remaining) + [ (Pair (Some "one") { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 22 (remaining gas: 1039983.340 units remaining) + [ {} + (Pair (Some "one") { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 24 (remaining gas: 1039983.265 units remaining) + [ (Pair {} (Some "one") { Elt "1" "one" ; Elt "2" "two" }) ] + - location: -1 (remaining gas: 1039983.220 units remaining) + [ (Pair {} (Some "one") { Elt "1" "one" ; Elt "2" "two" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt \"hello\" \"hi\" })-\"\"-(P.0c03056487.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt \"hello\" \"hi\" })-\"\"-(P.0c03056487.out" new file mode 100644 index 0000000000000000000000000000000000000000..a5f882eae42d980e30bc5a1470999171f383e7c7 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt \"hello\" \"hi\" })-\"\"-(P.0c03056487.out" @@ -0,0 +1,46 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt "hello" "hi" })-""-(Pair None { Elt "hello" "hi" })] + +storage + (Pair None { Elt "hello" "hi" }) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039984.923 units remaining) + [ (Pair "" None { Elt "hello" "hi" }) ] + - location: 12 (remaining gas: 1039984.843 units remaining) + [ (Pair "" None { Elt "hello" "hi" }) + (Pair "" None { Elt "hello" "hi" }) ] + - location: 13 (remaining gas: 1039984.763 units remaining) + [ "" @parameter + (Pair "" None { Elt "hello" "hi" }) ] + - location: 17 (remaining gas: 1039984.578 units remaining) + [ (Pair None { Elt "hello" "hi" }) @storage ] + - location: 18 (remaining gas: 1039984.498 units remaining) + [ { Elt "hello" "hi" } ] + - location: -1 (remaining gas: 1039984.453 units remaining) + [ { Elt "hello" "hi" } ] + - location: 19 (remaining gas: 1039984.373 units remaining) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: -1 (remaining gas: 1039984.328 units remaining) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 14 (remaining gas: 1039984.328 units remaining) + [ "" @parameter + { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 20 (remaining gas: 1039984.218 units remaining) + [ None + { Elt "hello" "hi" } ] + - location: 21 (remaining gas: 1039984.143 units remaining) + [ (Pair None { Elt "hello" "hi" }) ] + - location: 22 (remaining gas: 1039984.068 units remaining) + [ {} + (Pair None { Elt "hello" "hi" }) ] + - location: 24 (remaining gas: 1039983.993 units remaining) + [ (Pair {} None { Elt "hello" "hi" }) ] + - location: -1 (remaining gas: 1039983.948 units remaining) + [ (Pair {} None { Elt "hello" "hi" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt \"hello\" \"hi\" })-\"hell.cc45544c66.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt \"hello\" \"hi\" })-\"hell.cc45544c66.out" new file mode 100644 index 0000000000000000000000000000000000000000..5a40adb70a5dc7b7b5d851bbcc7fc051e562c03c --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt \"hello\" \"hi\" })-\"hell.cc45544c66.out" @@ -0,0 +1,46 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[get_map_value.tz-(Pair None { Elt "hello" "hi" })-"hello"-(Pair (Some "hi") { Elt "hello" "hi" })] + +storage + (Pair (Some "hi") { Elt "hello" "hi" }) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039984.873 units remaining) + [ (Pair "hello" None { Elt "hello" "hi" }) ] + - location: 12 (remaining gas: 1039984.793 units remaining) + [ (Pair "hello" None { Elt "hello" "hi" }) + (Pair "hello" None { Elt "hello" "hi" }) ] + - location: 13 (remaining gas: 1039984.713 units remaining) + [ "hello" @parameter + (Pair "hello" None { Elt "hello" "hi" }) ] + - location: 17 (remaining gas: 1039984.528 units remaining) + [ (Pair None { Elt "hello" "hi" }) @storage ] + - location: 18 (remaining gas: 1039984.448 units remaining) + [ { Elt "hello" "hi" } ] + - location: -1 (remaining gas: 1039984.403 units remaining) + [ { Elt "hello" "hi" } ] + - location: 19 (remaining gas: 1039984.323 units remaining) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: -1 (remaining gas: 1039984.278 units remaining) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 14 (remaining gas: 1039984.278 units remaining) + [ "hello" @parameter + { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 20 (remaining gas: 1039984.168 units remaining) + [ (Some "hi") + { Elt "hello" "hi" } ] + - location: 21 (remaining gas: 1039984.093 units remaining) + [ (Pair (Some "hi") { Elt "hello" "hi" }) ] + - location: 22 (remaining gas: 1039984.018 units remaining) + [ {} + (Pair (Some "hi") { Elt "hello" "hi" }) ] + - location: 24 (remaining gas: 1039983.943 units remaining) + [ (Pair {} (Some "hi") { Elt "hello" "hi" }) ] + - location: -1 (remaining gas: 1039983.898 units remaining) + [ (Pair {} (Some "hi") { Elt "hello" "hi" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_key.tz-None-\"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAb.613ad6b637.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_key.tz-None-\"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAb.613ad6b637.out" new file mode 100644 index 0000000000000000000000000000000000000000..6a2561953f6d7b3e5271074e8e05dc94d4fd1d32 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_key.tz-None-\"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAb.613ad6b637.out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[hash_key.tz-None-"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"-(Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx")] + +storage + (Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx") +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039964.690 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" None) ] + - location: 8 (remaining gas: 1039964.610 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" @parameter ] + - location: 9 (remaining gas: 1039964 units remaining) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 10 (remaining gas: 1039963.925 units remaining) + [ (Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx") ] + - location: 11 (remaining gas: 1039963.850 units remaining) + [ {} + (Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx") ] + - location: 13 (remaining gas: 1039963.775 units remaining) + [ (Pair {} (Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx")) ] + - location: -1 (remaining gas: 1039963.730 units remaining) + [ (Pair {} (Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_key.tz-None-\"edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTa.da50984e8d.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_key.tz-None-\"edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTa.da50984e8d.out" new file mode 100644 index 0000000000000000000000000000000000000000..a383ef839b6b344057fa04aa21a4e2af9684d17c --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_key.tz-None-\"edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTa.da50984e8d.out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[hash_key.tz-None-"edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTawUPqR8vZTAMcx61ES"-(Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k")] + +storage + (Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k") +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039964.690 units remaining) + [ (Pair "edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTawUPqR8vZTAMcx61ES" None) ] + - location: 8 (remaining gas: 1039964.610 units remaining) + [ "edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTawUPqR8vZTAMcx61ES" @parameter ] + - location: 9 (remaining gas: 1039964 units remaining) + [ "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k" ] + - location: 10 (remaining gas: 1039963.925 units remaining) + [ (Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k") ] + - location: 11 (remaining gas: 1039963.850 units remaining) + [ {} + (Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k") ] + - location: 13 (remaining gas: 1039963.775 units remaining) + [ (Pair {} (Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k")) ] + - location: -1 (remaining gas: 1039963.730 units remaining) + [ (Pair {} (Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_string.tz-0x00-\"12345\"-0xb4c26c20de52a4eaf0d8a340d.2bba28b0bf.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_string.tz-0x00-\"12345\"-0xb4c26c20de52a4eaf0d8a340d.2bba28b0bf.out" new file mode 100644 index 0000000000000000000000000000000000000000..e11bf81b5c2e40b17513f86ded7e864def29f787 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_string.tz-0x00-\"12345\"-0xb4c26c20de52a4eaf0d8a340d.2bba28b0bf.out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[hash_string.tz-0x00-"12345"-0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f] + +storage + 0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.926 units remaining) + [ (Pair "12345" 0x00) ] + - location: 7 (remaining gas: 1039993.846 units remaining) + [ "12345" @parameter ] + - location: 8 (remaining gas: 1039981.576 units remaining) + [ 0x0501000000053132333435 @parameter.packed ] + - location: 9 (remaining gas: 1039981.033 units remaining) + [ 0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f ] + - location: 10 (remaining gas: 1039980.958 units remaining) + [ {} + 0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f ] + - location: 12 (remaining gas: 1039980.883 units remaining) + [ (Pair {} 0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f) ] + - location: -1 (remaining gas: 1039980.838 units remaining) + [ (Pair {} 0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_string.tz-0x00-\"abcdefg\"-0x46fdbcb4ea4eadad5615cda.acc82cd954.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_string.tz-0x00-\"abcdefg\"-0x46fdbcb4ea4eadad5615cda.acc82cd954.out" new file mode 100644 index 0000000000000000000000000000000000000000..3b31029df98e079525ff44d67832d710c296aaed --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[hash_string.tz-0x00-\"abcdefg\"-0x46fdbcb4ea4eadad5615cda.acc82cd954.out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[hash_string.tz-0x00-"abcdefg"-0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e] + +storage + 0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039993.906 units remaining) + [ (Pair "abcdefg" 0x00) ] + - location: 7 (remaining gas: 1039993.826 units remaining) + [ "abcdefg" @parameter ] + - location: 8 (remaining gas: 1039981.556 units remaining) + [ 0x05010000000761626364656667 @parameter.packed ] + - location: 9 (remaining gas: 1039981.010 units remaining) + [ 0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e ] + - location: 10 (remaining gas: 1039980.935 units remaining) + [ {} + 0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e ] + - location: 12 (remaining gas: 1039980.860 units remaining) + [ (Pair {} 0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e) ] + - location: -1 (remaining gas: 1039980.815 units remaining) + [ (Pair {} 0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if.tz-None-False-(Some False)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if.tz-None-False-(Some False)].out new file mode 100644 index 0000000000000000000000000000000000000000..c6d8238efada9b529e8f8190a37bb9b7afead317 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if.tz-None-False-(Some False)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[if.tz-None-False-(Some False)] + +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039991.240 units remaining) + [ (Pair False None) ] + - location: 8 (remaining gas: 1039991.160 units remaining) + [ False @parameter ] + - location: 15 (remaining gas: 1039991.030 units remaining) + [ False ] + - location: 14 (remaining gas: 1039990.985 units remaining) + [ False ] + - location: 18 (remaining gas: 1039990.910 units remaining) + [ (Some False) ] + - location: 19 (remaining gas: 1039990.835 units remaining) + [ {} + (Some False) ] + - location: 21 (remaining gas: 1039990.760 units remaining) + [ (Pair {} (Some False)) ] + - location: -1 (remaining gas: 1039990.715 units remaining) + [ (Pair {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if.tz-None-True-(Some True)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if.tz-None-True-(Some True)].out new file mode 100644 index 0000000000000000000000000000000000000000..a4916a117942ac613fadcff1bd8bf3f90c4be780 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if.tz-None-True-(Some True)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[if.tz-None-True-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039991.240 units remaining) + [ (Pair True None) ] + - location: 8 (remaining gas: 1039991.160 units remaining) + [ True @parameter ] + - location: 11 (remaining gas: 1039991.030 units remaining) + [ True ] + - location: 10 (remaining gas: 1039990.985 units remaining) + [ True ] + - location: 18 (remaining gas: 1039990.910 units remaining) + [ (Some True) ] + - location: 19 (remaining gas: 1039990.835 units remaining) + [ {} + (Some True) ] + - location: 21 (remaining gas: 1039990.760 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039990.715 units remaining) + [ (Pair {} (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if_some.tz-\"?\"-(Some \"hello\")-\"hello\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if_some.tz-\"?\"-(Some \"hello\")-\"hello\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..b3fffdce17debb9524f4b43105bdad6b4b9e2489 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if_some.tz-\"?\"-(Some \"hello\")-\"hello\"].out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[if_some.tz-"?"-(Some "hello")-"hello"] + +storage + "hello" +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039992.188 units remaining) + [ (Pair (Some "hello") "?") ] + - location: 8 (remaining gas: 1039992.108 units remaining) + [ (Some "hello") @parameter ] + - location: 15 (remaining gas: 1039991.973 units remaining) + [ "hello" ] + - location: 9 (remaining gas: 1039991.928 units remaining) + [ "hello" ] + - location: 16 (remaining gas: 1039991.853 units remaining) + [ {} + "hello" ] + - location: 18 (remaining gas: 1039991.778 units remaining) + [ (Pair {} "hello") ] + - location: -1 (remaining gas: 1039991.733 units remaining) + [ (Pair {} "hello") ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if_some.tz-\"?\"-None-\"\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if_some.tz-\"?\"-None-\"\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..00e6f76b1f9fbc8016b44edbee4d8b17e22b8cae --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[if_some.tz-\"?\"-None-\"\"].out" @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[if_some.tz-"?"-None-""] + +storage + "" +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039992.492 units remaining) + [ (Pair None "?") ] + - location: 8 (remaining gas: 1039992.412 units remaining) + [ None @parameter ] + - location: 12 (remaining gas: 1039992.247 units remaining) + [ "" ] + - location: 11 (remaining gas: 1039992.202 units remaining) + [ "" ] + - location: 9 (remaining gas: 1039992.157 units remaining) + [ "" ] + - location: 16 (remaining gas: 1039992.082 units remaining) + [ {} + "" ] + - location: 18 (remaining gas: 1039992.007 units remaining) + [ (Pair {} "") ] + - location: -1 (remaining gas: 1039991.962 units remaining) + [ (Pair {} "") ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[int.tz-None-0-(Some 0)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[int.tz-None-0-(Some 0)].out new file mode 100644 index 0000000000000000000000000000000000000000..843729f78197cf864b5c986073f9bb4e26ffdc8b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[int.tz-None-0-(Some 0)].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[int.tz-None-0-(Some 0)] + +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.690 units remaining) + [ (Pair 0 None) ] + - location: 8 (remaining gas: 1039993.610 units remaining) + [ 0 @parameter ] + - location: 9 (remaining gas: 1039993.535 units remaining) + [ 0 ] + - location: 10 (remaining gas: 1039993.460 units remaining) + [ (Some 0) ] + - location: 11 (remaining gas: 1039993.385 units remaining) + [ {} + (Some 0) ] + - location: 13 (remaining gas: 1039993.310 units remaining) + [ (Pair {} (Some 0)) ] + - location: -1 (remaining gas: 1039993.265 units remaining) + [ (Pair {} (Some 0)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[int.tz-None-1-(Some 1)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[int.tz-None-1-(Some 1)].out new file mode 100644 index 0000000000000000000000000000000000000000..f21e19d8e996e4ad843386a101b2e065a1fcd4cb --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[int.tz-None-1-(Some 1)].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[int.tz-None-1-(Some 1)] + +storage + (Some 1) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.690 units remaining) + [ (Pair 1 None) ] + - location: 8 (remaining gas: 1039993.610 units remaining) + [ 1 @parameter ] + - location: 9 (remaining gas: 1039993.535 units remaining) + [ 1 ] + - location: 10 (remaining gas: 1039993.460 units remaining) + [ (Some 1) ] + - location: 11 (remaining gas: 1039993.385 units remaining) + [ {} + (Some 1) ] + - location: 13 (remaining gas: 1039993.310 units remaining) + [ (Pair {} (Some 1)) ] + - location: -1 (remaining gas: 1039993.265 units remaining) + [ (Pair {} (Some 1)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[int.tz-None-9999-(Some 9999)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[int.tz-None-9999-(Some 9999)].out new file mode 100644 index 0000000000000000000000000000000000000000..9c1a6c910471140cc8bd0250eefde5a1df9663fc --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[int.tz-None-9999-(Some 9999)].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[int.tz-None-9999-(Some 9999)] + +storage + (Some 9999) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.690 units remaining) + [ (Pair 9999 None) ] + - location: 8 (remaining gas: 1039993.610 units remaining) + [ 9999 @parameter ] + - location: 9 (remaining gas: 1039993.535 units remaining) + [ 9999 ] + - location: 10 (remaining gas: 1039993.460 units remaining) + [ (Some 9999) ] + - location: 11 (remaining gas: 1039993.385 units remaining) + [ {} + (Some 9999) ] + - location: 13 (remaining gas: 1039993.310 units remaining) + [ (Pair {} (Some 9999)) ] + - location: -1 (remaining gas: 1039993.265 units remaining) + [ (Pair {} (Some 9999)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[keccak.tz-None-0x48656c6c6f2c20776f726c6421-(Some 0xb6e.34c02678c9.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[keccak.tz-None-0x48656c6c6f2c20776f726c6421-(Some 0xb6e.34c02678c9.out new file mode 100644 index 0000000000000000000000000000000000000000..5f230dd70861e7c6d58a30a698859b4577ce0555 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[keccak.tz-None-0x48656c6c6f2c20776f726c6421-(Some 0xb6e.34c02678c9.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[keccak.tz-None-0x48656c6c6f2c20776f726c6421-(Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4)] + +storage + (Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.690 units remaining) + [ (Pair 0x48656c6c6f2c20776f726c6421 None) ] + - location: 8 (remaining gas: 1039993.610 units remaining) + [ 0x48656c6c6f2c20776f726c6421 @parameter ] + - location: 9 (remaining gas: 1039991.790 units remaining) + [ 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4 ] + - location: 10 (remaining gas: 1039991.715 units remaining) + [ (Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4) ] + - location: 11 (remaining gas: 1039991.640 units remaining) + [ {} + (Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4) ] + - location: 13 (remaining gas: 1039991.565 units remaining) + [ (Pair {} + (Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4)) ] + - location: -1 (remaining gas: 1039991.520 units remaining) + [ (Pair {} + (Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[left_right.tz-(Left \"X\")-(Left True)-(Right True)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[left_right.tz-(Left \"X\")-(Left True)-(Right True)].out" new file mode 100644 index 0000000000000000000000000000000000000000..33f0f28d9ba4a08ed959ed0951c7eb66fa0c4ca5 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[left_right.tz-(Left \"X\")-(Left True)-(Right True)].out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[left_right.tz-(Left "X")-(Left True)-(Right True)] + +storage + (Right True) +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039991.066 units remaining) + [ (Pair (Left True) (Left "X")) ] + - location: 11 (remaining gas: 1039990.986 units remaining) + [ (Left True) @parameter ] + - location: 14 (remaining gas: 1039990.851 units remaining) + [ (Right True) ] + - location: 13 (remaining gas: 1039990.806 units remaining) + [ (Right True) ] + - location: 19 (remaining gas: 1039990.731 units remaining) + [ {} + (Right True) ] + - location: 21 (remaining gas: 1039990.656 units remaining) + [ (Pair {} (Right True)) ] + - location: -1 (remaining gas: 1039990.611 units remaining) + [ (Pair {} (Right True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[left_right.tz-(Left \"X\")-(Right \"a\")-(Left \"a\")].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[left_right.tz-(Left \"X\")-(Right \"a\")-(Left \"a\")].out" new file mode 100644 index 0000000000000000000000000000000000000000..344304b828484bc9101f017321e49bc85ba15adb --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[left_right.tz-(Left \"X\")-(Right \"a\")-(Left \"a\")].out" @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[left_right.tz-(Left "X")-(Right "a")-(Left "a")] + +storage + (Left "a") +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039991.042 units remaining) + [ (Pair (Right "a") (Left "X")) ] + - location: 11 (remaining gas: 1039990.962 units remaining) + [ (Right "a") @parameter ] + - location: 17 (remaining gas: 1039990.827 units remaining) + [ (Left "a") ] + - location: 16 (remaining gas: 1039990.782 units remaining) + [ (Left "a") ] + - location: 19 (remaining gas: 1039990.707 units remaining) + [ {} + (Left "a") ] + - location: 21 (remaining gas: 1039990.632 units remaining) + [ (Pair {} (Left "a")) ] + - location: -1 (remaining gas: 1039990.587 units remaining) + [ (Pair {} (Left "a")) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[level.tz-111-Unit-1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[level.tz-111-Unit-1].out new file mode 100644 index 0000000000000000000000000000000000000000..ab731494e15d7a3137e05140f1d8f3fa85e8cd07 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[level.tz-111-Unit-1].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[level.tz-111-Unit-1] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit 111) ] + - location: 7 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 8 (remaining gas: 1039994.545 units remaining) + [ 1 @level ] + - location: 9 (remaining gas: 1039994.470 units remaining) + [ {} + 1 @level ] + - location: 11 (remaining gas: 1039994.395 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039994.350 units remaining) + [ (Pair {} 1) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat.tz-\"abc\"-{ \"d\" ; \"e\" ; \"f\" }-\"abcdef\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat.tz-\"abc\"-{ \"d\" ; \"e\" ; \"f\" }-\"abcdef\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..55e24562bae56b409429bcf3467c0c76e4f27019 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat.tz-\"abc\"-{ \"d\" ; \"e\" ; \"f\" }-\"abcdef\"].out" @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_concat.tz-"abc"-{ "d" ; "e" ; "f" }-"abcdef"] + +storage + "abcdef" +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039992.104 units remaining) + [ (Pair { "d" ; "e" ; "f" } "abc") ] + - location: 8 (remaining gas: 1039992.024 units remaining) + [ { "d" ; "e" ; "f" } @parameter + "abc" @storage ] + - location: 9 (remaining gas: 1039991.954 units remaining) + [ "abc" @storage + { "d" ; "e" ; "f" } @parameter ] + - location: 10 (remaining gas: 1039991.874 units remaining) + [ { "abc" ; "d" ; "e" ; "f" } ] + - location: 11 (remaining gas: 1039991.704 units remaining) + [ "abcdef" ] + - location: 12 (remaining gas: 1039991.629 units remaining) + [ {} + "abcdef" ] + - location: 14 (remaining gas: 1039991.554 units remaining) + [ (Pair {} "abcdef") ] + - location: -1 (remaining gas: 1039991.509 units remaining) + [ (Pair {} "abcdef") ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat.tz-\"abc\"-{}-\"abc\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat.tz-\"abc\"-{}-\"abc\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..f9716da3c42ef5069a2f7fd044e93d0442350cd0 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat.tz-\"abc\"-{}-\"abc\"].out" @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_concat.tz-"abc"-{}-"abc"] + +storage + "abc" +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039992.896 units remaining) + [ (Pair {} "abc") ] + - location: 8 (remaining gas: 1039992.816 units remaining) + [ {} @parameter + "abc" @storage ] + - location: 9 (remaining gas: 1039992.746 units remaining) + [ "abc" @storage + {} @parameter ] + - location: 10 (remaining gas: 1039992.666 units remaining) + [ { "abc" } ] + - location: 11 (remaining gas: 1039992.526 units remaining) + [ "abc" ] + - location: 12 (remaining gas: 1039992.451 units remaining) + [ {} + "abc" ] + - location: 14 (remaining gas: 1039992.376 units remaining) + [ (Pair {} "abc") ] + - location: -1 (remaining gas: 1039992.331 units remaining) + [ (Pair {} "abc") ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x-{ 0x00 ; 0x11 ; 0x00 }-0x001100].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x-{ 0x00 ; 0x11 ; 0x00 }-0x001100].out new file mode 100644 index 0000000000000000000000000000000000000000..756d062a773e43eb32e471c9010315b6209f86b0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x-{ 0x00 ; 0x11 ; 0x00 }-0x001100].out @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x-{ 0x00 ; 0x11 ; 0x00 }-0x001100] + +storage + 0x001100 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039992.220 units remaining) + [ (Pair { 0x00 ; 0x11 ; 0x00 } 0x) ] + - location: 8 (remaining gas: 1039992.140 units remaining) + [ { 0x00 ; 0x11 ; 0x00 } @parameter + 0x @storage ] + - location: 9 (remaining gas: 1039992.070 units remaining) + [ 0x @storage + { 0x00 ; 0x11 ; 0x00 } @parameter ] + - location: 10 (remaining gas: 1039991.990 units remaining) + [ { 0x ; 0x00 ; 0x11 ; 0x00 } ] + - location: 11 (remaining gas: 1039991.820 units remaining) + [ 0x001100 ] + - location: 12 (remaining gas: 1039991.745 units remaining) + [ {} + 0x001100 ] + - location: 14 (remaining gas: 1039991.670 units remaining) + [ (Pair {} 0x001100) ] + - location: -1 (remaining gas: 1039991.625 units remaining) + [ (Pair {} 0x001100) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x-{}-0x].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x-{}-0x].out new file mode 100644 index 0000000000000000000000000000000000000000..e93c3b701dd32d0139d78e8ce61b02baa368c953 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x-{}-0x].out @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x-{}-0x] + +storage + 0x +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039992.940 units remaining) + [ (Pair {} 0x) ] + - location: 8 (remaining gas: 1039992.860 units remaining) + [ {} @parameter + 0x @storage ] + - location: 9 (remaining gas: 1039992.790 units remaining) + [ 0x @storage + {} @parameter ] + - location: 10 (remaining gas: 1039992.710 units remaining) + [ { 0x } ] + - location: 11 (remaining gas: 1039992.570 units remaining) + [ 0x ] + - location: 12 (remaining gas: 1039992.495 units remaining) + [ {} + 0x ] + - location: 14 (remaining gas: 1039992.420 units remaining) + [ (Pair {} 0x) ] + - location: -1 (remaining gas: 1039992.375 units remaining) + [ (Pair {} 0x) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x00ab-{ 0xcd ; 0xef ; 0x00 }-0x00abcdef00].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x00ab-{ 0xcd ; 0xef ; 0x00 }-0x00abcdef00].out new file mode 100644 index 0000000000000000000000000000000000000000..9c742f80d5fbca234ab21df5da87735e98e03a6f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x00ab-{ 0xcd ; 0xef ; 0x00 }-0x00abcdef00].out @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0x00ab-{ 0xcd ; 0xef ; 0x00 }-0x00abcdef00] + +storage + 0x00abcdef00 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039992.220 units remaining) + [ (Pair { 0xcd ; 0xef ; 0x00 } 0x00ab) ] + - location: 8 (remaining gas: 1039992.140 units remaining) + [ { 0xcd ; 0xef ; 0x00 } @parameter + 0x00ab @storage ] + - location: 9 (remaining gas: 1039992.070 units remaining) + [ 0x00ab @storage + { 0xcd ; 0xef ; 0x00 } @parameter ] + - location: 10 (remaining gas: 1039991.990 units remaining) + [ { 0x00ab ; 0xcd ; 0xef ; 0x00 } ] + - location: 11 (remaining gas: 1039991.820 units remaining) + [ 0x00abcdef00 ] + - location: 12 (remaining gas: 1039991.745 units remaining) + [ {} + 0x00abcdef00 ] + - location: 14 (remaining gas: 1039991.670 units remaining) + [ (Pair {} 0x00abcdef00) ] + - location: -1 (remaining gas: 1039991.625 units remaining) + [ (Pair {} 0x00abcdef00) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0xabcd-{}-0xabcd].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0xabcd-{}-0xabcd].out new file mode 100644 index 0000000000000000000000000000000000000000..6f5efd73ed053a5ae631fff099abf46c9fe3712d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0xabcd-{}-0xabcd].out @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_concat_bytes.tz-0xabcd-{}-0xabcd] + +storage + 0xabcd +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039992.940 units remaining) + [ (Pair {} 0xabcd) ] + - location: 8 (remaining gas: 1039992.860 units remaining) + [ {} @parameter + 0xabcd @storage ] + - location: 9 (remaining gas: 1039992.790 units remaining) + [ 0xabcd @storage + {} @parameter ] + - location: 10 (remaining gas: 1039992.710 units remaining) + [ { 0xabcd } ] + - location: 11 (remaining gas: 1039992.570 units remaining) + [ 0xabcd ] + - location: 12 (remaining gas: 1039992.495 units remaining) + [ {} + 0xabcd ] + - location: 14 (remaining gas: 1039992.420 units remaining) + [ (Pair {} 0xabcd) ] + - location: -1 (remaining gas: 1039992.375 units remaining) + [ (Pair {} 0xabcd) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id.tz-{\"\"}-{ \"1\" ; \"2\" ; \"3\" }-{ \"1\" ; \"2\" ; \"3\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id.tz-{\"\"}-{ \"1\" ; \"2\" ; \"3\" }-{ \"1\" ; \"2\" ; \"3\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..90a6f9d58cf5814149fc2b2726d46d2d561ffcd7 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id.tz-{\"\"}-{ \"1\" ; \"2\" ; \"3\" }-{ \"1\" ; \"2\" ; \"3\" }].out" @@ -0,0 +1,21 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_id.tz-{""}-{ "1" ; "2" ; "3" }-{ "1" ; "2" ; "3" }] + +storage + { "1" ; "2" ; "3" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.974 units remaining) + [ (Pair { "1" ; "2" ; "3" } { "" }) ] + - location: 9 (remaining gas: 1039993.894 units remaining) + [ { "1" ; "2" ; "3" } @parameter ] + - location: 10 (remaining gas: 1039993.819 units remaining) + [ {} + { "1" ; "2" ; "3" } @parameter ] + - location: 12 (remaining gas: 1039993.744 units remaining) + [ (Pair {} { "1" ; "2" ; "3" }) ] + - location: -1 (remaining gas: 1039993.699 units remaining) + [ (Pair {} { "1" ; "2" ; "3" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id.tz-{\"\"}-{ \"a\" ; \"b\" ; \"c\" }-{ \"a\" ; \"b\" ; \"c\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id.tz-{\"\"}-{ \"a\" ; \"b\" ; \"c\" }-{ \"a\" ; \"b\" ; \"c\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..7530fd0e7c958acebc8f569a8f13832f881a7914 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id.tz-{\"\"}-{ \"a\" ; \"b\" ; \"c\" }-{ \"a\" ; \"b\" ; \"c\" }].out" @@ -0,0 +1,21 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_id.tz-{""}-{ "a" ; "b" ; "c" }-{ "a" ; "b" ; "c" }] + +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.974 units remaining) + [ (Pair { "a" ; "b" ; "c" } { "" }) ] + - location: 9 (remaining gas: 1039993.894 units remaining) + [ { "a" ; "b" ; "c" } @parameter ] + - location: 10 (remaining gas: 1039993.819 units remaining) + [ {} + { "a" ; "b" ; "c" } @parameter ] + - location: 12 (remaining gas: 1039993.744 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: -1 (remaining gas: 1039993.699 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id.tz-{\"\"}-{}-{}].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id.tz-{\"\"}-{}-{}].out" new file mode 100644 index 0000000000000000000000000000000000000000..37e17b19a7a4f69f0fb548f2287985e511d79b5f --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id.tz-{\"\"}-{}-{}].out" @@ -0,0 +1,21 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_id.tz-{""}-{}-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039994.766 units remaining) + [ (Pair {} { "" }) ] + - location: 9 (remaining gas: 1039994.686 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039994.611 units remaining) + [ {} + {} @parameter ] + - location: 12 (remaining gas: 1039994.536 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039994.491 units remaining) + [ (Pair {} {}) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id_map.tz-{\"\"}-{ \"1\" ; \"2\" ; \"3\" }-{ \"1\" ; \"2\" ; \"3\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id_map.tz-{\"\"}-{ \"1\" ; \"2\" ; \"3\" }-{ \"1\" ; \"2\" ; \"3\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..147daa838005b9acf0a3f94e7150633f4ab4d73c --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id_map.tz-{\"\"}-{ \"1\" ; \"2\" ; \"3\" }-{ \"1\" ; \"2\" ; \"3\" }].out" @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_id_map.tz-{""}-{ "1" ; "2" ; "3" }-{ "1" ; "2" ; "3" }] + +storage + { "1" ; "2" ; "3" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.849 units remaining) + [ (Pair { "1" ; "2" ; "3" } { "" }) ] + - location: 9 (remaining gas: 1039992.769 units remaining) + [ { "1" ; "2" ; "3" } @parameter ] + - location: 11 (remaining gas: 1039992.158 units remaining) + [ "1" @parameter.elt ] + - location: 11 (remaining gas: 1039992.113 units remaining) + [ "2" @parameter.elt ] + - location: 11 (remaining gas: 1039992.068 units remaining) + [ "3" @parameter.elt ] + - location: 10 (remaining gas: 1039992.068 units remaining) + [ { "1" ; "2" ; "3" } ] + - location: 12 (remaining gas: 1039991.993 units remaining) + [ {} + { "1" ; "2" ; "3" } ] + - location: 14 (remaining gas: 1039991.918 units remaining) + [ (Pair {} { "1" ; "2" ; "3" }) ] + - location: -1 (remaining gas: 1039991.873 units remaining) + [ (Pair {} { "1" ; "2" ; "3" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id_map.tz-{\"\"}-{ \"a\" ; \"b\" ; \"c\" }-{ \"a\" ; \"b\" ; \"c\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id_map.tz-{\"\"}-{ \"a\" ; \"b\" ; \"c\" }-{ \"a\" ; \"b\" ; \"c\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..c256920b6c2df764bcbe6c3f66217f2c1fd7a574 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id_map.tz-{\"\"}-{ \"a\" ; \"b\" ; \"c\" }-{ \"a\" ; \"b\" ; \"c\" }].out" @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_id_map.tz-{""}-{ "a" ; "b" ; "c" }-{ "a" ; "b" ; "c" }] + +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.849 units remaining) + [ (Pair { "a" ; "b" ; "c" } { "" }) ] + - location: 9 (remaining gas: 1039992.769 units remaining) + [ { "a" ; "b" ; "c" } @parameter ] + - location: 11 (remaining gas: 1039992.158 units remaining) + [ "a" @parameter.elt ] + - location: 11 (remaining gas: 1039992.113 units remaining) + [ "b" @parameter.elt ] + - location: 11 (remaining gas: 1039992.068 units remaining) + [ "c" @parameter.elt ] + - location: 10 (remaining gas: 1039992.068 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 12 (remaining gas: 1039991.993 units remaining) + [ {} + { "a" ; "b" ; "c" } ] + - location: 14 (remaining gas: 1039991.918 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: -1 (remaining gas: 1039991.873 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id_map.tz-{\"\"}-{}-{}].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id_map.tz-{\"\"}-{}-{}].out" new file mode 100644 index 0000000000000000000000000000000000000000..8940c1d82a7a081e54e417000db49eed7d70237c --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_id_map.tz-{\"\"}-{}-{}].out" @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_id_map.tz-{""}-{}-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.641 units remaining) + [ (Pair {} { "" }) ] + - location: 9 (remaining gas: 1039993.561 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039993.031 units remaining) + [ {} ] + - location: 12 (remaining gas: 1039992.956 units remaining) + [ {} + {} ] + - location: 14 (remaining gas: 1039992.881 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039992.836 units remaining) + [ (Pair {} {}) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_iter.tz-0-{ 10 ; 2 ; 1 }-20].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_iter.tz-0-{ 10 ; 2 ; 1 }-20].out new file mode 100644 index 0000000000000000000000000000000000000000..f3f24a470459e292976b6a184c8111add2298a7d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_iter.tz-0-{ 10 ; 2 ; 1 }-20].out @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_iter.tz-0-{ 10 ; 2 ; 1 }-20] + +storage + 20 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039991.060 units remaining) + [ (Pair { 10 ; 2 ; 1 } 0) ] + - location: 8 (remaining gas: 1039990.980 units remaining) + [ { 10 ; 2 ; 1 } @parameter ] + - location: 9 (remaining gas: 1039990.905 units remaining) + [ 1 + { 10 ; 2 ; 1 } @parameter ] + - location: 12 (remaining gas: 1039990.835 units remaining) + [ { 10 ; 2 ; 1 } @parameter + 1 ] + - location: 15 (remaining gas: 1039990.168 units remaining) + [ 10 ] + - location: 14 (remaining gas: 1039990.123 units remaining) + [ 10 ] + - location: 15 (remaining gas: 1039990.007 units remaining) + [ 20 ] + - location: 14 (remaining gas: 1039989.962 units remaining) + [ 20 ] + - location: 15 (remaining gas: 1039989.846 units remaining) + [ 20 ] + - location: 14 (remaining gas: 1039989.801 units remaining) + [ 20 ] + - location: 13 (remaining gas: 1039989.801 units remaining) + [ 20 ] + - location: 16 (remaining gas: 1039989.726 units remaining) + [ {} + 20 ] + - location: 18 (remaining gas: 1039989.651 units remaining) + [ (Pair {} 20) ] + - location: -1 (remaining gas: 1039989.606 units remaining) + [ (Pair {} 20) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_iter.tz-0-{ 3 ; 6 ; 9 }-162].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_iter.tz-0-{ 3 ; 6 ; 9 }-162].out new file mode 100644 index 0000000000000000000000000000000000000000..8c3af235ba4466b561843c0d252ed587df073a5d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_iter.tz-0-{ 3 ; 6 ; 9 }-162].out @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_iter.tz-0-{ 3 ; 6 ; 9 }-162] + +storage + 162 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039991.060 units remaining) + [ (Pair { 3 ; 6 ; 9 } 0) ] + - location: 8 (remaining gas: 1039990.980 units remaining) + [ { 3 ; 6 ; 9 } @parameter ] + - location: 9 (remaining gas: 1039990.905 units remaining) + [ 1 + { 3 ; 6 ; 9 } @parameter ] + - location: 12 (remaining gas: 1039990.835 units remaining) + [ { 3 ; 6 ; 9 } @parameter + 1 ] + - location: 15 (remaining gas: 1039990.168 units remaining) + [ 3 ] + - location: 14 (remaining gas: 1039990.123 units remaining) + [ 3 ] + - location: 15 (remaining gas: 1039990.007 units remaining) + [ 18 ] + - location: 14 (remaining gas: 1039989.962 units remaining) + [ 18 ] + - location: 15 (remaining gas: 1039989.846 units remaining) + [ 162 ] + - location: 14 (remaining gas: 1039989.801 units remaining) + [ 162 ] + - location: 13 (remaining gas: 1039989.801 units remaining) + [ 162 ] + - location: 16 (remaining gas: 1039989.726 units remaining) + [ {} + 162 ] + - location: 18 (remaining gas: 1039989.651 units remaining) + [ (Pair {} 162) ] + - location: -1 (remaining gas: 1039989.606 units remaining) + [ (Pair {} 162) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{ 1 ; 1 ; 1 ; 1 }-{ 1 ; 2 ; 3 ; 4 }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{ 1 ; 1 ; 1 ; 1 }-{ 1 ; 2 ; 3 ; 4 }].out new file mode 100644 index 0000000000000000000000000000000000000000..1eaf05f875ea64a496cd9795aff548853f1c4436 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{ 1 ; 1 ; 1 ; 1 }-{ 1 ; 2 ; 3 ; 4 }].out @@ -0,0 +1,142 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{ 1 ; 1 ; 1 ; 1 }-{ 1 ; 2 ; 3 ; 4 }] + +storage + { 1 ; 2 ; 3 ; 4 } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039984.380 units remaining) + [ (Pair { 1 ; 1 ; 1 ; 1 } { 0 }) ] + - location: 9 (remaining gas: 1039984.300 units remaining) + [ { 1 ; 1 ; 1 ; 1 } @parameter ] + - location: 10 (remaining gas: 1039984.225 units remaining) + [ 0 + { 1 ; 1 ; 1 ; 1 } @parameter ] + - location: 13 (remaining gas: 1039984.155 units remaining) + [ { 1 ; 1 ; 1 ; 1 } @parameter + 0 ] + - location: 18 (remaining gas: 1039983.422 units remaining) + [ 0 + 0 ] + - location: 17 (remaining gas: 1039983.377 units remaining) + [ 0 + 0 ] + - location: 16 (remaining gas: 1039983.377 units remaining) + [ 1 @parameter.elt + 0 + 0 ] + - location: 19 (remaining gas: 1039983.267 units remaining) + [ 1 + 0 ] + - location: 22 (remaining gas: 1039983.117 units remaining) + [ 1 + 0 ] + - location: 25 (remaining gas: 1039983.007 units remaining) + [ 1 ] + - location: -1 (remaining gas: 1039982.962 units remaining) + [ 1 ] + - location: 20 (remaining gas: 1039982.962 units remaining) + [ 1 + 1 ] + - location: -1 (remaining gas: 1039982.917 units remaining) + [ 1 + 1 ] + - location: 18 (remaining gas: 1039982.762 units remaining) + [ 1 + 1 ] + - location: 17 (remaining gas: 1039982.717 units remaining) + [ 1 + 1 ] + - location: 16 (remaining gas: 1039982.717 units remaining) + [ 1 @parameter.elt + 1 + 1 ] + - location: 19 (remaining gas: 1039982.607 units remaining) + [ 2 + 1 ] + - location: 22 (remaining gas: 1039982.457 units remaining) + [ 1 + 1 ] + - location: 25 (remaining gas: 1039982.347 units remaining) + [ 2 ] + - location: -1 (remaining gas: 1039982.302 units remaining) + [ 2 ] + - location: 20 (remaining gas: 1039982.302 units remaining) + [ 2 + 2 ] + - location: -1 (remaining gas: 1039982.257 units remaining) + [ 2 + 2 ] + - location: 18 (remaining gas: 1039982.102 units remaining) + [ 2 + 2 ] + - location: 17 (remaining gas: 1039982.057 units remaining) + [ 2 + 2 ] + - location: 16 (remaining gas: 1039982.057 units remaining) + [ 1 @parameter.elt + 2 + 2 ] + - location: 19 (remaining gas: 1039981.947 units remaining) + [ 3 + 2 ] + - location: 22 (remaining gas: 1039981.797 units remaining) + [ 1 + 2 ] + - location: 25 (remaining gas: 1039981.687 units remaining) + [ 3 ] + - location: -1 (remaining gas: 1039981.642 units remaining) + [ 3 ] + - location: 20 (remaining gas: 1039981.642 units remaining) + [ 3 + 3 ] + - location: -1 (remaining gas: 1039981.597 units remaining) + [ 3 + 3 ] + - location: 18 (remaining gas: 1039981.442 units remaining) + [ 3 + 3 ] + - location: 17 (remaining gas: 1039981.397 units remaining) + [ 3 + 3 ] + - location: 16 (remaining gas: 1039981.397 units remaining) + [ 1 @parameter.elt + 3 + 3 ] + - location: 19 (remaining gas: 1039981.287 units remaining) + [ 4 + 3 ] + - location: 22 (remaining gas: 1039981.137 units remaining) + [ 1 + 3 ] + - location: 25 (remaining gas: 1039981.027 units remaining) + [ 4 ] + - location: -1 (remaining gas: 1039980.982 units remaining) + [ 4 ] + - location: 20 (remaining gas: 1039980.982 units remaining) + [ 4 + 4 ] + - location: -1 (remaining gas: 1039980.937 units remaining) + [ 4 + 4 ] + - location: 14 (remaining gas: 1039980.937 units remaining) + [ { 1 ; 2 ; 3 ; 4 } + 4 ] + - location: 26 (remaining gas: 1039980.862 units remaining) + [ {} + { 1 ; 2 ; 3 ; 4 } + 4 ] + - location: 28 (remaining gas: 1039980.787 units remaining) + [ (Pair {} { 1 ; 2 ; 3 ; 4 }) + 4 ] + - location: 31 (remaining gas: 1039980.637 units remaining) + [ ] + - location: 30 (remaining gas: 1039980.592 units remaining) + [ ] + - location: 29 (remaining gas: 1039980.592 units remaining) + [ (Pair {} { 1 ; 2 ; 3 ; 4 }) ] + - location: -1 (remaining gas: 1039980.547 units remaining) + [ (Pair {} { 1 ; 2 ; 3 ; 4 }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{ 1 ; 2 ; 3 ; 0 }-{ 1 ; 3 ; 5 ; 3 }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{ 1 ; 2 ; 3 ; 0 }-{ 1 ; 3 ; 5 ; 3 }].out new file mode 100644 index 0000000000000000000000000000000000000000..045d85c520bd6fa54505eb8ea87ae521467ad70d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{ 1 ; 2 ; 3 ; 0 }-{ 1 ; 3 ; 5 ; 3 }].out @@ -0,0 +1,142 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{ 1 ; 2 ; 3 ; 0 }-{ 1 ; 3 ; 5 ; 3 }] + +storage + { 1 ; 3 ; 5 ; 3 } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039984.380 units remaining) + [ (Pair { 1 ; 2 ; 3 ; 0 } { 0 }) ] + - location: 9 (remaining gas: 1039984.300 units remaining) + [ { 1 ; 2 ; 3 ; 0 } @parameter ] + - location: 10 (remaining gas: 1039984.225 units remaining) + [ 0 + { 1 ; 2 ; 3 ; 0 } @parameter ] + - location: 13 (remaining gas: 1039984.155 units remaining) + [ { 1 ; 2 ; 3 ; 0 } @parameter + 0 ] + - location: 18 (remaining gas: 1039983.422 units remaining) + [ 0 + 0 ] + - location: 17 (remaining gas: 1039983.377 units remaining) + [ 0 + 0 ] + - location: 16 (remaining gas: 1039983.377 units remaining) + [ 1 @parameter.elt + 0 + 0 ] + - location: 19 (remaining gas: 1039983.267 units remaining) + [ 1 + 0 ] + - location: 22 (remaining gas: 1039983.117 units remaining) + [ 1 + 0 ] + - location: 25 (remaining gas: 1039983.007 units remaining) + [ 1 ] + - location: -1 (remaining gas: 1039982.962 units remaining) + [ 1 ] + - location: 20 (remaining gas: 1039982.962 units remaining) + [ 1 + 1 ] + - location: -1 (remaining gas: 1039982.917 units remaining) + [ 1 + 1 ] + - location: 18 (remaining gas: 1039982.762 units remaining) + [ 1 + 1 ] + - location: 17 (remaining gas: 1039982.717 units remaining) + [ 1 + 1 ] + - location: 16 (remaining gas: 1039982.717 units remaining) + [ 2 @parameter.elt + 1 + 1 ] + - location: 19 (remaining gas: 1039982.607 units remaining) + [ 3 + 1 ] + - location: 22 (remaining gas: 1039982.457 units remaining) + [ 1 + 1 ] + - location: 25 (remaining gas: 1039982.347 units remaining) + [ 2 ] + - location: -1 (remaining gas: 1039982.302 units remaining) + [ 2 ] + - location: 20 (remaining gas: 1039982.302 units remaining) + [ 3 + 2 ] + - location: -1 (remaining gas: 1039982.257 units remaining) + [ 3 + 2 ] + - location: 18 (remaining gas: 1039982.102 units remaining) + [ 2 + 2 ] + - location: 17 (remaining gas: 1039982.057 units remaining) + [ 2 + 2 ] + - location: 16 (remaining gas: 1039982.057 units remaining) + [ 3 @parameter.elt + 2 + 2 ] + - location: 19 (remaining gas: 1039981.947 units remaining) + [ 5 + 2 ] + - location: 22 (remaining gas: 1039981.797 units remaining) + [ 1 + 2 ] + - location: 25 (remaining gas: 1039981.687 units remaining) + [ 3 ] + - location: -1 (remaining gas: 1039981.642 units remaining) + [ 3 ] + - location: 20 (remaining gas: 1039981.642 units remaining) + [ 5 + 3 ] + - location: -1 (remaining gas: 1039981.597 units remaining) + [ 5 + 3 ] + - location: 18 (remaining gas: 1039981.442 units remaining) + [ 3 + 3 ] + - location: 17 (remaining gas: 1039981.397 units remaining) + [ 3 + 3 ] + - location: 16 (remaining gas: 1039981.397 units remaining) + [ 0 @parameter.elt + 3 + 3 ] + - location: 19 (remaining gas: 1039981.287 units remaining) + [ 3 + 3 ] + - location: 22 (remaining gas: 1039981.137 units remaining) + [ 1 + 3 ] + - location: 25 (remaining gas: 1039981.027 units remaining) + [ 4 ] + - location: -1 (remaining gas: 1039980.982 units remaining) + [ 4 ] + - location: 20 (remaining gas: 1039980.982 units remaining) + [ 3 + 4 ] + - location: -1 (remaining gas: 1039980.937 units remaining) + [ 3 + 4 ] + - location: 14 (remaining gas: 1039980.937 units remaining) + [ { 1 ; 3 ; 5 ; 3 } + 4 ] + - location: 26 (remaining gas: 1039980.862 units remaining) + [ {} + { 1 ; 3 ; 5 ; 3 } + 4 ] + - location: 28 (remaining gas: 1039980.787 units remaining) + [ (Pair {} { 1 ; 3 ; 5 ; 3 }) + 4 ] + - location: 31 (remaining gas: 1039980.637 units remaining) + [ ] + - location: 30 (remaining gas: 1039980.592 units remaining) + [ ] + - location: 29 (remaining gas: 1039980.592 units remaining) + [ (Pair {} { 1 ; 3 ; 5 ; 3 }) ] + - location: -1 (remaining gas: 1039980.547 units remaining) + [ (Pair {} { 1 ; 3 ; 5 ; 3 }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{}-{}].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{}-{}].out new file mode 100644 index 0000000000000000000000000000000000000000..526ca26e3bac5af8129f9dd23e6c2e3e8ec9d8d8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{}-{}].out @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_map_block.tz-{0}-{}-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039985.340 units remaining) + [ (Pair {} { 0 }) ] + - location: 9 (remaining gas: 1039985.260 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039985.185 units remaining) + [ 0 + {} @parameter ] + - location: 13 (remaining gas: 1039985.115 units remaining) + [ {} @parameter + 0 ] + - location: 14 (remaining gas: 1039984.585 units remaining) + [ {} + 0 ] + - location: 26 (remaining gas: 1039984.510 units remaining) + [ {} + {} + 0 ] + - location: 28 (remaining gas: 1039984.435 units remaining) + [ (Pair {} {}) + 0 ] + - location: 31 (remaining gas: 1039984.285 units remaining) + [ ] + - location: 30 (remaining gas: 1039984.240 units remaining) + [ ] + - location: 29 (remaining gas: 1039984.240 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039984.195 units remaining) + [ (Pair {} {}) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }-6].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }-6].out new file mode 100644 index 0000000000000000000000000000000000000000..d9e7fc6651fb48c3752ccd66dc4026ca72d0493e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }-6].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }-6] + +storage + 6 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.130 units remaining) + [ (Pair { 1 ; 2 ; 3 ; 4 ; 5 ; 6 } 111) ] + - location: 8 (remaining gas: 1039993.050 units remaining) + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 } @parameter ] + - location: 9 (remaining gas: 1039992.970 units remaining) + [ 6 ] + - location: 10 (remaining gas: 1039992.895 units remaining) + [ {} + 6 ] + - location: 12 (remaining gas: 1039992.820 units remaining) + [ (Pair {} 6) ] + - location: -1 (remaining gas: 1039992.775 units remaining) + [ (Pair {} 6) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 ; 2 ; 3 }-3].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 ; 2 ; 3 }-3].out new file mode 100644 index 0000000000000000000000000000000000000000..82ab3157c1abf00040a49caedf01b1584fc5efd5 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 ; 2 ; 3 }-3].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 ; 2 ; 3 }-3] + +storage + 3 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.850 units remaining) + [ (Pair { 1 ; 2 ; 3 } 111) ] + - location: 8 (remaining gas: 1039993.770 units remaining) + [ { 1 ; 2 ; 3 } @parameter ] + - location: 9 (remaining gas: 1039993.690 units remaining) + [ 3 ] + - location: 10 (remaining gas: 1039993.615 units remaining) + [ {} + 3 ] + - location: 12 (remaining gas: 1039993.540 units remaining) + [ (Pair {} 3) ] + - location: -1 (remaining gas: 1039993.495 units remaining) + [ (Pair {} 3) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 }-1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 }-1].out new file mode 100644 index 0000000000000000000000000000000000000000..ea8ed71e92f2f65fb5416801c3a3ce1889eadbf7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 }-1].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_size.tz-111-{ 1 }-1] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.330 units remaining) + [ (Pair { 1 } 111) ] + - location: 8 (remaining gas: 1039994.250 units remaining) + [ { 1 } @parameter ] + - location: 9 (remaining gas: 1039994.170 units remaining) + [ 1 ] + - location: 10 (remaining gas: 1039994.095 units remaining) + [ {} + 1 ] + - location: 12 (remaining gas: 1039994.020 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039993.975 units remaining) + [ (Pair {} 1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{}-0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{}-0].out new file mode 100644 index 0000000000000000000000000000000000000000..b291d16dcdce7a4883b88ad3f40cfdf97831813e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[list_size.tz-111-{}-0].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[list_size.tz-111-{}-0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.570 units remaining) + [ (Pair {} 111) ] + - location: 8 (remaining gas: 1039994.490 units remaining) + [ {} @parameter ] + - location: 9 (remaining gas: 1039994.410 units remaining) + [ 0 ] + - location: 10 (remaining gas: 1039994.335 units remaining) + [ {} + 0 ] + - location: 12 (remaining gas: 1039994.260 units remaining) + [ (Pair {} 0) ] + - location: -1 (remaining gas: 1039994.215 units remaining) + [ (Pair {} 0) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[loop_left.tz-{\"\"}-{ \"c\" ; \"b\" ; \"a\" }-{ \"a\" ; \"b\" ; \"c\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[loop_left.tz-{\"\"}-{ \"c\" ; \"b\" ; \"a\" }-{ \"a\" ; \"b\" ; \"c\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..49deae8491d06c0ba2ccbbb7943606c64f7340e5 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[loop_left.tz-{\"\"}-{ \"c\" ; \"b\" ; \"a\" }-{ \"a\" ; \"b\" ; \"c\" }].out" @@ -0,0 +1,148 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[loop_left.tz-{""}-{ "c" ; "b" ; "a" }-{ "a" ; "b" ; "c" }] + +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039976.864 units remaining) + [ (Pair { "c" ; "b" ; "a" } { "" }) ] + - location: 9 (remaining gas: 1039976.784 units remaining) + [ { "c" ; "b" ; "a" } @parameter ] + - location: 10 (remaining gas: 1039976.709 units remaining) + [ {} + { "c" ; "b" ; "a" } @parameter ] + - location: 12 (remaining gas: 1039976.639 units remaining) + [ { "c" ; "b" ; "a" } @parameter + {} ] + - location: 13 (remaining gas: 1039976.564 units remaining) + [ (Pair { "c" ; "b" ; "a" } {}) ] + - location: 14 (remaining gas: 1039976.489 units remaining) + [ (Left (Pair { "c" ; "b" ; "a" } {})) ] + - location: 19 (remaining gas: 1039976.334 units remaining) + [ (Pair { "c" ; "b" ; "a" } {}) + (Pair { "c" ; "b" ; "a" } {}) ] + - location: 20 (remaining gas: 1039976.254 units remaining) + [ { "c" ; "b" ; "a" } @parameter + (Pair { "c" ; "b" ; "a" } {}) ] + - location: 23 (remaining gas: 1039976.099 units remaining) + [ {} ] + - location: 22 (remaining gas: 1039976.054 units remaining) + [ {} ] + - location: 21 (remaining gas: 1039976.054 units remaining) + [ { "c" ; "b" ; "a" } @parameter + {} ] + - location: 26 (remaining gas: 1039975.924 units remaining) + [ { "b" ; "a" } @parameter.tl + "c" @parameter.hd + {} ] + - location: 29 (remaining gas: 1039975.769 units remaining) + [ { "c" } ] + - location: 28 (remaining gas: 1039975.724 units remaining) + [ { "c" } ] + - location: 27 (remaining gas: 1039975.724 units remaining) + [ { "b" ; "a" } @parameter.tl + { "c" } ] + - location: 30 (remaining gas: 1039975.649 units remaining) + [ (Pair { "b" ; "a" } { "c" }) ] + - location: 31 (remaining gas: 1039975.574 units remaining) + [ (Left (Pair { "b" ; "a" } { "c" })) ] + - location: -1 (remaining gas: 1039975.529 units remaining) + [ (Left (Pair { "b" ; "a" } { "c" })) ] + - location: -1 (remaining gas: 1039975.484 units remaining) + [ (Left (Pair { "b" ; "a" } { "c" })) ] + - location: 19 (remaining gas: 1039975.359 units remaining) + [ (Pair { "b" ; "a" } { "c" }) + (Pair { "b" ; "a" } { "c" }) ] + - location: 20 (remaining gas: 1039975.279 units remaining) + [ { "b" ; "a" } @parameter + (Pair { "b" ; "a" } { "c" }) ] + - location: 23 (remaining gas: 1039975.124 units remaining) + [ { "c" } ] + - location: 22 (remaining gas: 1039975.079 units remaining) + [ { "c" } ] + - location: 21 (remaining gas: 1039975.079 units remaining) + [ { "b" ; "a" } @parameter + { "c" } ] + - location: 26 (remaining gas: 1039974.949 units remaining) + [ { "a" } @parameter.tl + "b" @parameter.hd + { "c" } ] + - location: 29 (remaining gas: 1039974.794 units remaining) + [ { "b" ; "c" } ] + - location: 28 (remaining gas: 1039974.749 units remaining) + [ { "b" ; "c" } ] + - location: 27 (remaining gas: 1039974.749 units remaining) + [ { "a" } @parameter.tl + { "b" ; "c" } ] + - location: 30 (remaining gas: 1039974.674 units remaining) + [ (Pair { "a" } { "b" ; "c" }) ] + - location: 31 (remaining gas: 1039974.599 units remaining) + [ (Left (Pair { "a" } { "b" ; "c" })) ] + - location: -1 (remaining gas: 1039974.554 units remaining) + [ (Left (Pair { "a" } { "b" ; "c" })) ] + - location: -1 (remaining gas: 1039974.509 units remaining) + [ (Left (Pair { "a" } { "b" ; "c" })) ] + - location: 19 (remaining gas: 1039974.384 units remaining) + [ (Pair { "a" } { "b" ; "c" }) + (Pair { "a" } { "b" ; "c" }) ] + - location: 20 (remaining gas: 1039974.304 units remaining) + [ { "a" } @parameter + (Pair { "a" } { "b" ; "c" }) ] + - location: 23 (remaining gas: 1039974.149 units remaining) + [ { "b" ; "c" } ] + - location: 22 (remaining gas: 1039974.104 units remaining) + [ { "b" ; "c" } ] + - location: 21 (remaining gas: 1039974.104 units remaining) + [ { "a" } @parameter + { "b" ; "c" } ] + - location: 26 (remaining gas: 1039973.974 units remaining) + [ {} @parameter.tl + "a" @parameter.hd + { "b" ; "c" } ] + - location: 29 (remaining gas: 1039973.819 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 28 (remaining gas: 1039973.774 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 27 (remaining gas: 1039973.774 units remaining) + [ {} @parameter.tl + { "a" ; "b" ; "c" } ] + - location: 30 (remaining gas: 1039973.699 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: 31 (remaining gas: 1039973.624 units remaining) + [ (Left (Pair {} { "a" ; "b" ; "c" })) ] + - location: -1 (remaining gas: 1039973.579 units remaining) + [ (Left (Pair {} { "a" ; "b" ; "c" })) ] + - location: -1 (remaining gas: 1039973.534 units remaining) + [ (Left (Pair {} { "a" ; "b" ; "c" })) ] + - location: 19 (remaining gas: 1039973.409 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) + (Pair {} { "a" ; "b" ; "c" }) ] + - location: 20 (remaining gas: 1039973.329 units remaining) + [ {} @parameter + (Pair {} { "a" ; "b" ; "c" }) ] + - location: 23 (remaining gas: 1039973.174 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 22 (remaining gas: 1039973.129 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 21 (remaining gas: 1039973.129 units remaining) + [ {} @parameter + { "a" ; "b" ; "c" } ] + - location: 35 (remaining gas: 1039972.994 units remaining) + [ (Right { "a" ; "b" ; "c" }) ] + - location: 34 (remaining gas: 1039972.949 units remaining) + [ (Right { "a" ; "b" ; "c" }) ] + - location: -1 (remaining gas: 1039972.904 units remaining) + [ (Right { "a" ; "b" ; "c" }) ] + - location: 17 (remaining gas: 1039972.859 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 41 (remaining gas: 1039972.784 units remaining) + [ {} + { "a" ; "b" ; "c" } ] + - location: 43 (remaining gas: 1039972.709 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: -1 (remaining gas: 1039972.664 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[loop_left.tz-{\"\"}-{}-{}].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[loop_left.tz-{\"\"}-{}-{}].out" new file mode 100644 index 0000000000000000000000000000000000000000..44bbf3c0910c5e345c58582d301cba01d158f8c9 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[loop_left.tz-{\"\"}-{}-{}].out" @@ -0,0 +1,52 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[loop_left.tz-{""}-{}-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039977.656 units remaining) + [ (Pair {} { "" }) ] + - location: 9 (remaining gas: 1039977.576 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039977.501 units remaining) + [ {} + {} @parameter ] + - location: 12 (remaining gas: 1039977.431 units remaining) + [ {} @parameter + {} ] + - location: 13 (remaining gas: 1039977.356 units remaining) + [ (Pair {} {}) ] + - location: 14 (remaining gas: 1039977.281 units remaining) + [ (Left (Pair {} {})) ] + - location: 19 (remaining gas: 1039977.126 units remaining) + [ (Pair {} {}) + (Pair {} {}) ] + - location: 20 (remaining gas: 1039977.046 units remaining) + [ {} @parameter + (Pair {} {}) ] + - location: 23 (remaining gas: 1039976.891 units remaining) + [ {} ] + - location: 22 (remaining gas: 1039976.846 units remaining) + [ {} ] + - location: 21 (remaining gas: 1039976.846 units remaining) + [ {} @parameter + {} ] + - location: 35 (remaining gas: 1039976.711 units remaining) + [ (Right {}) ] + - location: 34 (remaining gas: 1039976.666 units remaining) + [ (Right {}) ] + - location: -1 (remaining gas: 1039976.621 units remaining) + [ (Right {}) ] + - location: 17 (remaining gas: 1039976.576 units remaining) + [ {} ] + - location: 41 (remaining gas: 1039976.501 units remaining) + [ {} + {} ] + - location: 43 (remaining gas: 1039976.426 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039976.381 units remaining) + [ (Pair {} {}) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 0 ; Elt 3 4 }-{ Elt 0 0 ; Elt 3 4 }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 0 ; Elt 3 4 }-{ Elt 0 0 ; Elt 3 4 }].out new file mode 100644 index 0000000000000000000000000000000000000000..2c4900e27a44e0d288d063d3dd1eb4fa7c2bc77c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 0 ; Elt 3 4 }-{ Elt 0 0 ; Elt 3 4 }].out @@ -0,0 +1,21 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 0 ; Elt 3 4 }-{ Elt 0 0 ; Elt 3 4 }] + +storage + { Elt 0 0 ; Elt 3 4 } +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039993.280 units remaining) + [ (Pair { Elt 0 0 ; Elt 3 4 } {}) ] + - location: 11 (remaining gas: 1039993.200 units remaining) + [ { Elt 0 0 ; Elt 3 4 } @parameter ] + - location: 12 (remaining gas: 1039993.125 units remaining) + [ {} + { Elt 0 0 ; Elt 3 4 } @parameter ] + - location: 14 (remaining gas: 1039993.050 units remaining) + [ (Pair {} { Elt 0 0 ; Elt 3 4 }) ] + - location: -1 (remaining gas: 1039993.005 units remaining) + [ (Pair {} { Elt 0 0 ; Elt 3 4 }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 0 }-{ Elt 0 0 }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 0 }-{ Elt 0 0 }].out new file mode 100644 index 0000000000000000000000000000000000000000..9ea53ce13671585b58f8ef22e8469f2b00538a2c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 0 }-{ Elt 0 0 }].out @@ -0,0 +1,21 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 0 }-{ Elt 0 0 }] + +storage + { Elt 0 0 } +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039993.990 units remaining) + [ (Pair { Elt 0 0 } {}) ] + - location: 11 (remaining gas: 1039993.910 units remaining) + [ { Elt 0 0 } @parameter ] + - location: 12 (remaining gas: 1039993.835 units remaining) + [ {} + { Elt 0 0 } @parameter ] + - location: 14 (remaining gas: 1039993.760 units remaining) + [ (Pair {} { Elt 0 0 }) ] + - location: -1 (remaining gas: 1039993.715 units remaining) + [ (Pair {} { Elt 0 0 }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 1 }-{ Elt 0 1 }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 1 }-{ Elt 0 1 }].out new file mode 100644 index 0000000000000000000000000000000000000000..448649892f5cd88323a4f74ed50eef86f2e7e2e5 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 1 }-{ Elt 0 1 }].out @@ -0,0 +1,21 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_id.tz-{}-{ Elt 0 1 }-{ Elt 0 1 }] + +storage + { Elt 0 1 } +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039993.990 units remaining) + [ (Pair { Elt 0 1 } {}) ] + - location: 11 (remaining gas: 1039993.910 units remaining) + [ { Elt 0 1 } @parameter ] + - location: 12 (remaining gas: 1039993.835 units remaining) + [ {} + { Elt 0 1 } @parameter ] + - location: 14 (remaining gas: 1039993.760 units remaining) + [ (Pair {} { Elt 0 1 }) ] + - location: -1 (remaining gas: 1039993.715 units remaining) + [ (Pair {} { Elt 0 1 }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_iter.tz-(Pair 0 0)-{ Elt 0 100 ; Elt 2 100 }-(Pair 2 200)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_iter.tz-(Pair 0 0)-{ Elt 0 100 ; Elt 2 100 }-(Pair 2 200)].out new file mode 100644 index 0000000000000000000000000000000000000000..867fef28176ea62364b0225fe05dc84128d3c40c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_iter.tz-(Pair 0 0)-{ Elt 0 100 ; Elt 2 100 }-(Pair 2 200)].out @@ -0,0 +1,150 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_iter.tz-(Pair 0 0)-{ Elt 0 100 ; Elt 2 100 }-(Pair 2 200)] + +storage + (Pair 2 200) +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039975.900 units remaining) + [ (Pair { Elt 0 100 ; Elt 2 100 } 0 0) ] + - location: 11 (remaining gas: 1039975.820 units remaining) + [ { Elt 0 100 ; Elt 2 100 } @parameter ] + - location: 12 (remaining gas: 1039975.745 units remaining) + [ 0 @acc_e + { Elt 0 100 ; Elt 2 100 } @parameter ] + - location: 15 (remaining gas: 1039975.670 units remaining) + [ 0 @acc_k + 0 @acc_e + { Elt 0 100 ; Elt 2 100 } @parameter ] + - location: 18 (remaining gas: 1039975.595 units remaining) + [ (Pair 0 0) + { Elt 0 100 ; Elt 2 100 } @parameter ] + - location: 19 (remaining gas: 1039975.525 units remaining) + [ { Elt 0 100 ; Elt 2 100 } @parameter + (Pair 0 0) ] + - location: 24 (remaining gas: 1039975.180 units remaining) + [ (Pair 0 0) + (Pair 0 0) ] + - location: 25 (remaining gas: 1039975.100 units remaining) + [ 0 @acc_k + (Pair 0 0) ] + - location: 28 (remaining gas: 1039974.945 units remaining) + [ 0 @acc_e ] + - location: 27 (remaining gas: 1039974.900 units remaining) + [ 0 @acc_e ] + - location: 26 (remaining gas: 1039974.900 units remaining) + [ 0 @acc_k + 0 @acc_e ] + - location: -1 (remaining gas: 1039974.855 units remaining) + [ 0 @acc_k + 0 @acc_e ] + - location: 22 (remaining gas: 1039974.855 units remaining) + [ (Pair 0 100) + 0 @acc_k + 0 @acc_e ] + - location: 29 (remaining gas: 1039974.775 units remaining) + [ (Pair 0 100) + (Pair 0 100) + 0 @acc_k + 0 @acc_e ] + - location: 32 (remaining gas: 1039974.620 units remaining) + [ 0 @key + 0 @acc_k + 0 @acc_e ] + - location: 33 (remaining gas: 1039974.510 units remaining) + [ 0 + 0 @acc_e ] + - location: -1 (remaining gas: 1039974.465 units remaining) + [ 0 + 0 @acc_e ] + - location: 30 (remaining gas: 1039974.465 units remaining) + [ (Pair 0 100) + 0 + 0 @acc_e ] + - location: 34 (remaining gas: 1039974.395 units remaining) + [ 0 + (Pair 0 100) + 0 @acc_e ] + - location: 37 (remaining gas: 1039974.240 units remaining) + [ 100 @elt + 0 @acc_e ] + - location: 38 (remaining gas: 1039974.130 units remaining) + [ 100 ] + - location: -1 (remaining gas: 1039974.085 units remaining) + [ 100 ] + - location: 35 (remaining gas: 1039974.085 units remaining) + [ 0 + 100 ] + - location: 39 (remaining gas: 1039974.010 units remaining) + [ (Pair 0 100) ] + - location: -1 (remaining gas: 1039973.965 units remaining) + [ (Pair 0 100) ] + - location: 24 (remaining gas: 1039973.810 units remaining) + [ (Pair 0 100) + (Pair 0 100) ] + - location: 25 (remaining gas: 1039973.730 units remaining) + [ 0 @acc_k + (Pair 0 100) ] + - location: 28 (remaining gas: 1039973.575 units remaining) + [ 100 @acc_e ] + - location: 27 (remaining gas: 1039973.530 units remaining) + [ 100 @acc_e ] + - location: 26 (remaining gas: 1039973.530 units remaining) + [ 0 @acc_k + 100 @acc_e ] + - location: -1 (remaining gas: 1039973.485 units remaining) + [ 0 @acc_k + 100 @acc_e ] + - location: 22 (remaining gas: 1039973.485 units remaining) + [ (Pair 2 100) + 0 @acc_k + 100 @acc_e ] + - location: 29 (remaining gas: 1039973.405 units remaining) + [ (Pair 2 100) + (Pair 2 100) + 0 @acc_k + 100 @acc_e ] + - location: 32 (remaining gas: 1039973.250 units remaining) + [ 2 @key + 0 @acc_k + 100 @acc_e ] + - location: 33 (remaining gas: 1039973.140 units remaining) + [ 2 + 100 @acc_e ] + - location: -1 (remaining gas: 1039973.095 units remaining) + [ 2 + 100 @acc_e ] + - location: 30 (remaining gas: 1039973.095 units remaining) + [ (Pair 2 100) + 2 + 100 @acc_e ] + - location: 34 (remaining gas: 1039973.025 units remaining) + [ 2 + (Pair 2 100) + 100 @acc_e ] + - location: 37 (remaining gas: 1039972.870 units remaining) + [ 100 @elt + 100 @acc_e ] + - location: 38 (remaining gas: 1039972.760 units remaining) + [ 200 ] + - location: -1 (remaining gas: 1039972.715 units remaining) + [ 200 ] + - location: 35 (remaining gas: 1039972.715 units remaining) + [ 2 + 200 ] + - location: 39 (remaining gas: 1039972.640 units remaining) + [ (Pair 2 200) ] + - location: -1 (remaining gas: 1039972.595 units remaining) + [ (Pair 2 200) ] + - location: 20 (remaining gas: 1039972.595 units remaining) + [ (Pair 2 200) ] + - location: 40 (remaining gas: 1039972.520 units remaining) + [ {} + (Pair 2 200) ] + - location: 42 (remaining gas: 1039972.445 units remaining) + [ (Pair {} 2 200) ] + - location: -1 (remaining gas: 1039972.400 units remaining) + [ (Pair {} 2 200) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_iter.tz-(Pair 0 0)-{ Elt 1 1 ; Elt 2 100 }-(Pair 3 101)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_iter.tz-(Pair 0 0)-{ Elt 1 1 ; Elt 2 100 }-(Pair 3 101)].out new file mode 100644 index 0000000000000000000000000000000000000000..514585b58ca03b055321e0f83c50a1e316f8eeb5 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_iter.tz-(Pair 0 0)-{ Elt 1 1 ; Elt 2 100 }-(Pair 3 101)].out @@ -0,0 +1,150 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_iter.tz-(Pair 0 0)-{ Elt 1 1 ; Elt 2 100 }-(Pair 3 101)] + +storage + (Pair 3 101) +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039975.900 units remaining) + [ (Pair { Elt 1 1 ; Elt 2 100 } 0 0) ] + - location: 11 (remaining gas: 1039975.820 units remaining) + [ { Elt 1 1 ; Elt 2 100 } @parameter ] + - location: 12 (remaining gas: 1039975.745 units remaining) + [ 0 @acc_e + { Elt 1 1 ; Elt 2 100 } @parameter ] + - location: 15 (remaining gas: 1039975.670 units remaining) + [ 0 @acc_k + 0 @acc_e + { Elt 1 1 ; Elt 2 100 } @parameter ] + - location: 18 (remaining gas: 1039975.595 units remaining) + [ (Pair 0 0) + { Elt 1 1 ; Elt 2 100 } @parameter ] + - location: 19 (remaining gas: 1039975.525 units remaining) + [ { Elt 1 1 ; Elt 2 100 } @parameter + (Pair 0 0) ] + - location: 24 (remaining gas: 1039975.180 units remaining) + [ (Pair 0 0) + (Pair 0 0) ] + - location: 25 (remaining gas: 1039975.100 units remaining) + [ 0 @acc_k + (Pair 0 0) ] + - location: 28 (remaining gas: 1039974.945 units remaining) + [ 0 @acc_e ] + - location: 27 (remaining gas: 1039974.900 units remaining) + [ 0 @acc_e ] + - location: 26 (remaining gas: 1039974.900 units remaining) + [ 0 @acc_k + 0 @acc_e ] + - location: -1 (remaining gas: 1039974.855 units remaining) + [ 0 @acc_k + 0 @acc_e ] + - location: 22 (remaining gas: 1039974.855 units remaining) + [ (Pair 1 1) + 0 @acc_k + 0 @acc_e ] + - location: 29 (remaining gas: 1039974.775 units remaining) + [ (Pair 1 1) + (Pair 1 1) + 0 @acc_k + 0 @acc_e ] + - location: 32 (remaining gas: 1039974.620 units remaining) + [ 1 @key + 0 @acc_k + 0 @acc_e ] + - location: 33 (remaining gas: 1039974.510 units remaining) + [ 1 + 0 @acc_e ] + - location: -1 (remaining gas: 1039974.465 units remaining) + [ 1 + 0 @acc_e ] + - location: 30 (remaining gas: 1039974.465 units remaining) + [ (Pair 1 1) + 1 + 0 @acc_e ] + - location: 34 (remaining gas: 1039974.395 units remaining) + [ 1 + (Pair 1 1) + 0 @acc_e ] + - location: 37 (remaining gas: 1039974.240 units remaining) + [ 1 @elt + 0 @acc_e ] + - location: 38 (remaining gas: 1039974.130 units remaining) + [ 1 ] + - location: -1 (remaining gas: 1039974.085 units remaining) + [ 1 ] + - location: 35 (remaining gas: 1039974.085 units remaining) + [ 1 + 1 ] + - location: 39 (remaining gas: 1039974.010 units remaining) + [ (Pair 1 1) ] + - location: -1 (remaining gas: 1039973.965 units remaining) + [ (Pair 1 1) ] + - location: 24 (remaining gas: 1039973.810 units remaining) + [ (Pair 1 1) + (Pair 1 1) ] + - location: 25 (remaining gas: 1039973.730 units remaining) + [ 1 @acc_k + (Pair 1 1) ] + - location: 28 (remaining gas: 1039973.575 units remaining) + [ 1 @acc_e ] + - location: 27 (remaining gas: 1039973.530 units remaining) + [ 1 @acc_e ] + - location: 26 (remaining gas: 1039973.530 units remaining) + [ 1 @acc_k + 1 @acc_e ] + - location: -1 (remaining gas: 1039973.485 units remaining) + [ 1 @acc_k + 1 @acc_e ] + - location: 22 (remaining gas: 1039973.485 units remaining) + [ (Pair 2 100) + 1 @acc_k + 1 @acc_e ] + - location: 29 (remaining gas: 1039973.405 units remaining) + [ (Pair 2 100) + (Pair 2 100) + 1 @acc_k + 1 @acc_e ] + - location: 32 (remaining gas: 1039973.250 units remaining) + [ 2 @key + 1 @acc_k + 1 @acc_e ] + - location: 33 (remaining gas: 1039973.140 units remaining) + [ 3 + 1 @acc_e ] + - location: -1 (remaining gas: 1039973.095 units remaining) + [ 3 + 1 @acc_e ] + - location: 30 (remaining gas: 1039973.095 units remaining) + [ (Pair 2 100) + 3 + 1 @acc_e ] + - location: 34 (remaining gas: 1039973.025 units remaining) + [ 3 + (Pair 2 100) + 1 @acc_e ] + - location: 37 (remaining gas: 1039972.870 units remaining) + [ 100 @elt + 1 @acc_e ] + - location: 38 (remaining gas: 1039972.760 units remaining) + [ 101 ] + - location: -1 (remaining gas: 1039972.715 units remaining) + [ 101 ] + - location: 35 (remaining gas: 1039972.715 units remaining) + [ 3 + 101 ] + - location: 39 (remaining gas: 1039972.640 units remaining) + [ (Pair 3 101) ] + - location: -1 (remaining gas: 1039972.595 units remaining) + [ (Pair 3 101) ] + - location: 20 (remaining gas: 1039972.595 units remaining) + [ (Pair 3 101) ] + - location: 40 (remaining gas: 1039972.520 units remaining) + [ {} + (Pair 3 101) ] + - location: 42 (remaining gas: 1039972.445 units remaining) + [ (Pair {} 3 101) ] + - location: -1 (remaining gas: 1039972.400 units remaining) + [ (Pair {} 3 101) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_map.tz-{ Elt \"bar\" 5 ; Elt \"foo\" 1 }-15-{ Elt \"bar\".12b9d73d5a.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_map.tz-{ Elt \"bar\" 5 ; Elt \"foo\" 1 }-15-{ Elt \"bar\".12b9d73d5a.out" new file mode 100644 index 0000000000000000000000000000000000000000..7e38fce3f46c1aa47c0eb06901bb28279814b33b --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_map.tz-{ Elt \"bar\" 5 ; Elt \"foo\" 1 }-15-{ Elt \"bar\".12b9d73d5a.out" @@ -0,0 +1,72 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_map.tz-{ Elt "bar" 5 ; Elt "foo" 1 }-15-{ Elt "bar" 20 ; Elt "foo" 16 }] + +storage + { Elt "bar" 20 ; Elt "foo" 16 } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039987.192 units remaining) + [ (Pair 15 { Elt "bar" 5 ; Elt "foo" 1 }) ] + - location: 9 (remaining gas: 1039987.112 units remaining) + [ 15 @parameter + { Elt "bar" 5 ; Elt "foo" 1 } @storage ] + - location: 10 (remaining gas: 1039987.042 units remaining) + [ { Elt "bar" 5 ; Elt "foo" 1 } @storage + 15 @parameter ] + - location: 13 (remaining gas: 1039985.330 units remaining) + [ 5 @elt + 15 @parameter ] + - location: 16 (remaining gas: 1039985.175 units remaining) + [ 15 @parameter + 15 @parameter ] + - location: 15 (remaining gas: 1039985.130 units remaining) + [ 15 @parameter + 15 @parameter ] + - location: 14 (remaining gas: 1039985.130 units remaining) + [ 5 @elt + 15 @parameter + 15 @parameter ] + - location: 17 (remaining gas: 1039985.020 units remaining) + [ 20 + 15 @parameter ] + - location: -1 (remaining gas: 1039984.975 units remaining) + [ 20 + 15 @parameter ] + - location: 13 (remaining gas: 1039984.895 units remaining) + [ 1 @elt + 15 @parameter ] + - location: 16 (remaining gas: 1039984.740 units remaining) + [ 15 @parameter + 15 @parameter ] + - location: 15 (remaining gas: 1039984.695 units remaining) + [ 15 @parameter + 15 @parameter ] + - location: 14 (remaining gas: 1039984.695 units remaining) + [ 1 @elt + 15 @parameter + 15 @parameter ] + - location: 17 (remaining gas: 1039984.585 units remaining) + [ 16 + 15 @parameter ] + - location: -1 (remaining gas: 1039984.540 units remaining) + [ 16 + 15 @parameter ] + - location: 11 (remaining gas: 1039984.540 units remaining) + [ { Elt "bar" 20 ; Elt "foo" 16 } + 15 @parameter ] + - location: 20 (remaining gas: 1039984.390 units remaining) + [ ] + - location: 19 (remaining gas: 1039984.345 units remaining) + [ ] + - location: 18 (remaining gas: 1039984.345 units remaining) + [ { Elt "bar" 20 ; Elt "foo" 16 } ] + - location: 21 (remaining gas: 1039984.270 units remaining) + [ {} + { Elt "bar" 20 ; Elt "foo" 16 } ] + - location: 23 (remaining gas: 1039984.195 units remaining) + [ (Pair {} { Elt "bar" 20 ; Elt "foo" 16 }) ] + - location: -1 (remaining gas: 1039984.150 units remaining) + [ (Pair {} { Elt "bar" 20 ; Elt "foo" 16 }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_map.tz-{ Elt \"foo\" 1 }-10-{ Elt \"foo\" 11 }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_map.tz-{ Elt \"foo\" 1 }-10-{ Elt \"foo\" 11 }].out" new file mode 100644 index 0000000000000000000000000000000000000000..96df627e6907715692cd82164fa5ba0ddd53af04 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_map.tz-{ Elt \"foo\" 1 }-10-{ Elt \"foo\" 11 }].out" @@ -0,0 +1,53 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_map.tz-{ Elt "foo" 1 }-10-{ Elt "foo" 11 }] + +storage + { Elt "foo" 11 } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039987.916 units remaining) + [ (Pair 10 { Elt "foo" 1 }) ] + - location: 9 (remaining gas: 1039987.836 units remaining) + [ 10 @parameter + { Elt "foo" 1 } @storage ] + - location: 10 (remaining gas: 1039987.766 units remaining) + [ { Elt "foo" 1 } @storage + 10 @parameter ] + - location: 13 (remaining gas: 1039986.815 units remaining) + [ 1 @elt + 10 @parameter ] + - location: 16 (remaining gas: 1039986.660 units remaining) + [ 10 @parameter + 10 @parameter ] + - location: 15 (remaining gas: 1039986.615 units remaining) + [ 10 @parameter + 10 @parameter ] + - location: 14 (remaining gas: 1039986.615 units remaining) + [ 1 @elt + 10 @parameter + 10 @parameter ] + - location: 17 (remaining gas: 1039986.505 units remaining) + [ 11 + 10 @parameter ] + - location: -1 (remaining gas: 1039986.460 units remaining) + [ 11 + 10 @parameter ] + - location: 11 (remaining gas: 1039986.460 units remaining) + [ { Elt "foo" 11 } + 10 @parameter ] + - location: 20 (remaining gas: 1039986.310 units remaining) + [ ] + - location: 19 (remaining gas: 1039986.265 units remaining) + [ ] + - location: 18 (remaining gas: 1039986.265 units remaining) + [ { Elt "foo" 11 } ] + - location: 21 (remaining gas: 1039986.190 units remaining) + [ {} + { Elt "foo" 11 } ] + - location: 23 (remaining gas: 1039986.115 units remaining) + [ (Pair {} { Elt "foo" 11 }) ] + - location: -1 (remaining gas: 1039986.070 units remaining) + [ (Pair {} { Elt "foo" 11 }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_map.tz-{}-10-{}].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_map.tz-{}-10-{}].out new file mode 100644 index 0000000000000000000000000000000000000000..b5cbdc007fc0e79c7efabf8899c62959df05573b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_map.tz-{}-10-{}].out @@ -0,0 +1,34 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_map.tz-{}-10-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039988.520 units remaining) + [ (Pair 10 {}) ] + - location: 9 (remaining gas: 1039988.440 units remaining) + [ 10 @parameter + {} @storage ] + - location: 10 (remaining gas: 1039988.370 units remaining) + [ {} @storage + 10 @parameter ] + - location: 11 (remaining gas: 1039988.260 units remaining) + [ {} + 10 @parameter ] + - location: 20 (remaining gas: 1039988.110 units remaining) + [ ] + - location: 19 (remaining gas: 1039988.065 units remaining) + [ ] + - location: 18 (remaining gas: 1039988.065 units remaining) + [ {} ] + - location: 21 (remaining gas: 1039987.990 units remaining) + [ {} + {} ] + - location: 23 (remaining gas: 1039987.915 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039987.870 units remaining) + [ (Pair {} {}) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair { Elt 0 .7396e5f090.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair { Elt 0 .7396e5f090.out new file mode 100644 index 0000000000000000000000000000000000000000..05cd141c3ddb39cc5f15875fcecbbfc70c94985b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair { Elt 0 .7396e5f090.out @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 0 1 } None)-1-(Pair { Elt 0 1 } (Some False))] + +storage + (Pair { Elt 0 1 } (Some False)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039987.090 units remaining) + [ (Pair 1 { Elt 0 1 } None) ] + - location: 12 (remaining gas: 1039987.010 units remaining) + [ 1 @parameter + (Pair { Elt 0 1 } None) @storage ] + - location: 15 (remaining gas: 1039986.855 units remaining) + [ { Elt 0 1 } ] + - location: 16 (remaining gas: 1039986.775 units remaining) + [ { Elt 0 1 } + { Elt 0 1 } ] + - location: -1 (remaining gas: 1039986.730 units remaining) + [ { Elt 0 1 } + { Elt 0 1 } ] + - location: 13 (remaining gas: 1039986.730 units remaining) + [ 1 @parameter + { Elt 0 1 } + { Elt 0 1 } ] + - location: 17 (remaining gas: 1039986.620 units remaining) + [ False + { Elt 0 1 } ] + - location: 18 (remaining gas: 1039986.545 units remaining) + [ (Some False) + { Elt 0 1 } ] + - location: 19 (remaining gas: 1039986.475 units remaining) + [ { Elt 0 1 } + (Some False) ] + - location: 20 (remaining gas: 1039986.400 units remaining) + [ (Pair { Elt 0 1 } (Some False)) ] + - location: 21 (remaining gas: 1039986.325 units remaining) + [ {} + (Pair { Elt 0 1 } (Some False)) ] + - location: 23 (remaining gas: 1039986.250 units remaining) + [ (Pair {} { Elt 0 1 } (Some False)) ] + - location: -1 (remaining gas: 1039986.205 units remaining) + [ (Pair {} { Elt 0 1 } (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair { Elt 1 .cef8ce601a.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair { Elt 1 .cef8ce601a.out new file mode 100644 index 0000000000000000000000000000000000000000..7e8ae99dbb22bb1c79d74f989215cd39a6fa054a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair { Elt 1 .cef8ce601a.out @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 0 } None)-1-(Pair { Elt 1 0 } (Some True))] + +storage + (Pair { Elt 1 0 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039987.090 units remaining) + [ (Pair 1 { Elt 1 0 } None) ] + - location: 12 (remaining gas: 1039987.010 units remaining) + [ 1 @parameter + (Pair { Elt 1 0 } None) @storage ] + - location: 15 (remaining gas: 1039986.855 units remaining) + [ { Elt 1 0 } ] + - location: 16 (remaining gas: 1039986.775 units remaining) + [ { Elt 1 0 } + { Elt 1 0 } ] + - location: -1 (remaining gas: 1039986.730 units remaining) + [ { Elt 1 0 } + { Elt 1 0 } ] + - location: 13 (remaining gas: 1039986.730 units remaining) + [ 1 @parameter + { Elt 1 0 } + { Elt 1 0 } ] + - location: 17 (remaining gas: 1039986.620 units remaining) + [ True + { Elt 1 0 } ] + - location: 18 (remaining gas: 1039986.545 units remaining) + [ (Some True) + { Elt 1 0 } ] + - location: 19 (remaining gas: 1039986.475 units remaining) + [ { Elt 1 0 } + (Some True) ] + - location: 20 (remaining gas: 1039986.400 units remaining) + [ (Pair { Elt 1 0 } (Some True)) ] + - location: 21 (remaining gas: 1039986.325 units remaining) + [ {} + (Pair { Elt 1 0 } (Some True)) ] + - location: 23 (remaining gas: 1039986.250 units remaining) + [ (Pair {} { Elt 1 0 } (Some True)) ] + - location: -1 (remaining gas: 1039986.205 units remaining) + [ (Pair {} { Elt 1 0 } (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1-(Pa.1a55a5bfa5.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1-(Pa.1a55a5bfa5.out new file mode 100644 index 0000000000000000000000000000000000000000..7f9da2f61bf6a418a80f97c61860be03a9958f24 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1-(Pa.1a55a5bfa5.out @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-1-(Pair { Elt 1 4 ; Elt 2 11 } (Some True))] + +storage + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039986.380 units remaining) + [ (Pair 1 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (remaining gas: 1039986.300 units remaining) + [ 1 @parameter + (Pair { Elt 1 4 ; Elt 2 11 } None) @storage ] + - location: 15 (remaining gas: 1039986.145 units remaining) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (remaining gas: 1039986.065 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: -1 (remaining gas: 1039986.020 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (remaining gas: 1039986.020 units remaining) + [ 1 @parameter + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (remaining gas: 1039985.910 units remaining) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (remaining gas: 1039985.835 units remaining) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (remaining gas: 1039985.765 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (remaining gas: 1039985.690 units remaining) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (remaining gas: 1039985.615 units remaining) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (remaining gas: 1039985.540 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: -1 (remaining gas: 1039985.495 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2-(Pa.89cc24d256.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2-(Pa.89cc24d256.out new file mode 100644 index 0000000000000000000000000000000000000000..c1ad1df871fdb65aa2ee0a19780fa3d17d0008d5 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2-(Pa.89cc24d256.out @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-2-(Pair { Elt 1 4 ; Elt 2 11 } (Some True))] + +storage + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039986.380 units remaining) + [ (Pair 2 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (remaining gas: 1039986.300 units remaining) + [ 2 @parameter + (Pair { Elt 1 4 ; Elt 2 11 } None) @storage ] + - location: 15 (remaining gas: 1039986.145 units remaining) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (remaining gas: 1039986.065 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: -1 (remaining gas: 1039986.020 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (remaining gas: 1039986.020 units remaining) + [ 2 @parameter + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (remaining gas: 1039985.910 units remaining) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (remaining gas: 1039985.835 units remaining) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (remaining gas: 1039985.765 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (remaining gas: 1039985.690 units remaining) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (remaining gas: 1039985.615 units remaining) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (remaining gas: 1039985.540 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: -1 (remaining gas: 1039985.495 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3-(Pa.2fba3165c0.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3-(Pa.2fba3165c0.out new file mode 100644 index 0000000000000000000000000000000000000000..49fb280ce8cf1a2b0ba3612828e25ef132b206ea --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3-(Pa.2fba3165c0.out @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair { Elt 1 4 ; Elt 2 11 } None)-3-(Pair { Elt 1 4 ; Elt 2 11 } (Some False))] + +storage + (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039986.380 units remaining) + [ (Pair 3 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (remaining gas: 1039986.300 units remaining) + [ 3 @parameter + (Pair { Elt 1 4 ; Elt 2 11 } None) @storage ] + - location: 15 (remaining gas: 1039986.145 units remaining) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (remaining gas: 1039986.065 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: -1 (remaining gas: 1039986.020 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (remaining gas: 1039986.020 units remaining) + [ 3 @parameter + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (remaining gas: 1039985.910 units remaining) + [ False + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (remaining gas: 1039985.835 units remaining) + [ (Some False) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (remaining gas: 1039985.765 units remaining) + [ { Elt 1 4 ; Elt 2 11 } + (Some False) ] + - location: 20 (remaining gas: 1039985.690 units remaining) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 21 (remaining gas: 1039985.615 units remaining) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 23 (remaining gas: 1039985.540 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: -1 (remaining gas: 1039985.495 units remaining) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair {} None)-1-(Pair {} (Some False))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair {} None)-1-(Pair {} (Some False))].out new file mode 100644 index 0000000000000000000000000000000000000000..48dad279f2df116a98fe9fec3d110641e7ecd4b7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair {} None)-1-(Pair {} (Some False))].out @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_nat.tz-(Pair {} None)-1-(Pair {} (Some False))] + +storage + (Pair {} (Some False)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039987.650 units remaining) + [ (Pair 1 {} None) ] + - location: 12 (remaining gas: 1039987.570 units remaining) + [ 1 @parameter + (Pair {} None) @storage ] + - location: 15 (remaining gas: 1039987.415 units remaining) + [ {} ] + - location: 16 (remaining gas: 1039987.335 units remaining) + [ {} + {} ] + - location: -1 (remaining gas: 1039987.290 units remaining) + [ {} + {} ] + - location: 13 (remaining gas: 1039987.290 units remaining) + [ 1 @parameter + {} + {} ] + - location: 17 (remaining gas: 1039987.180 units remaining) + [ False + {} ] + - location: 18 (remaining gas: 1039987.105 units remaining) + [ (Some False) + {} ] + - location: 19 (remaining gas: 1039987.035 units remaining) + [ {} + (Some False) ] + - location: 20 (remaining gas: 1039986.960 units remaining) + [ (Pair {} (Some False)) ] + - location: 21 (remaining gas: 1039986.885 units remaining) + [ {} + (Pair {} (Some False)) ] + - location: 23 (remaining gas: 1039986.810 units remaining) + [ (Pair {} {} (Some False)) ] + - location: -1 (remaining gas: 1039986.765 units remaining) + [ (Pair {} {} (Some False)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 11 } .6d625e02a5.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 11 } .6d625e02a5.out" new file mode 100644 index 0000000000000000000000000000000000000000..1dd5934cf243e26a411c0528e269a84fd94127a0 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 11 } .6d625e02a5.out" @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)-"bar"-(Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True))] + +storage + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039986.278 units remaining) + [ (Pair "bar" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (remaining gas: 1039986.198 units remaining) + [ "bar" @parameter + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) @storage ] + - location: 15 (remaining gas: 1039986.043 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (remaining gas: 1039985.963 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: -1 (remaining gas: 1039985.918 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (remaining gas: 1039985.918 units remaining) + [ "bar" @parameter + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (remaining gas: 1039985.808 units remaining) + [ True + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (remaining gas: 1039985.733 units remaining) + [ (Some True) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (remaining gas: 1039985.663 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some True) ] + - location: 20 (remaining gas: 1039985.588 units remaining) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 21 (remaining gas: 1039985.513 units remaining) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 23 (remaining gas: 1039985.438 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: -1 (remaining gas: 1039985.393 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 11 } .a7e3837a82.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 11 } .a7e3837a82.out" new file mode 100644 index 0000000000000000000000000000000000000000..d8cd900830487dc1a7e45ba24a4f4c3fef4b7e51 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 11 } .a7e3837a82.out" @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)-"foo"-(Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True))] + +storage + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039986.278 units remaining) + [ (Pair "foo" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (remaining gas: 1039986.198 units remaining) + [ "foo" @parameter + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) @storage ] + - location: 15 (remaining gas: 1039986.043 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (remaining gas: 1039985.963 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: -1 (remaining gas: 1039985.918 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (remaining gas: 1039985.918 units remaining) + [ "foo" @parameter + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (remaining gas: 1039985.808 units remaining) + [ True + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (remaining gas: 1039985.733 units remaining) + [ (Some True) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (remaining gas: 1039985.663 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some True) ] + - location: 20 (remaining gas: 1039985.588 units remaining) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 21 (remaining gas: 1039985.513 units remaining) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 23 (remaining gas: 1039985.438 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: -1 (remaining gas: 1039985.393 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 11 } .c7716fe79e.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 11 } .c7716fe79e.out" new file mode 100644 index 0000000000000000000000000000000000000000..9c7cf313a7649296bd795ee472600430896c13cf --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"bar\" 4 ; Elt \"foo\" 11 } .c7716fe79e.out" @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)-"baz"-(Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False))] + +storage + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039986.278 units remaining) + [ (Pair "baz" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (remaining gas: 1039986.198 units remaining) + [ "baz" @parameter + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) @storage ] + - location: 15 (remaining gas: 1039986.043 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (remaining gas: 1039985.963 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: -1 (remaining gas: 1039985.918 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (remaining gas: 1039985.918 units remaining) + [ "baz" @parameter + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (remaining gas: 1039985.808 units remaining) + [ False + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (remaining gas: 1039985.733 units remaining) + [ (Some False) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (remaining gas: 1039985.663 units remaining) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some False) ] + - location: 20 (remaining gas: 1039985.588 units remaining) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: 21 (remaining gas: 1039985.513 units remaining) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: 23 (remaining gas: 1039985.438 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: -1 (remaining gas: 1039985.393 units remaining) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"foo\" 0 } None)-\"foo\"-(Pa.7861a3b1e2.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"foo\" 0 } None)-\"foo\"-(Pa.7861a3b1e2.out" new file mode 100644 index 0000000000000000000000000000000000000000..655ce77ca1cae833ef754a89062b2e4c9cd1345c --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"foo\" 0 } None)-\"foo\"-(Pa.7861a3b1e2.out" @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt "foo" 0 } None)-"foo"-(Pair { Elt "foo" 0 } (Some True))] + +storage + (Pair { Elt "foo" 0 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039987.002 units remaining) + [ (Pair "foo" { Elt "foo" 0 } None) ] + - location: 12 (remaining gas: 1039986.922 units remaining) + [ "foo" @parameter + (Pair { Elt "foo" 0 } None) @storage ] + - location: 15 (remaining gas: 1039986.767 units remaining) + [ { Elt "foo" 0 } ] + - location: 16 (remaining gas: 1039986.687 units remaining) + [ { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: -1 (remaining gas: 1039986.642 units remaining) + [ { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: 13 (remaining gas: 1039986.642 units remaining) + [ "foo" @parameter + { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: 17 (remaining gas: 1039986.532 units remaining) + [ True + { Elt "foo" 0 } ] + - location: 18 (remaining gas: 1039986.457 units remaining) + [ (Some True) + { Elt "foo" 0 } ] + - location: 19 (remaining gas: 1039986.387 units remaining) + [ { Elt "foo" 0 } + (Some True) ] + - location: 20 (remaining gas: 1039986.312 units remaining) + [ (Pair { Elt "foo" 0 } (Some True)) ] + - location: 21 (remaining gas: 1039986.237 units remaining) + [ {} + (Pair { Elt "foo" 0 } (Some True)) ] + - location: 23 (remaining gas: 1039986.162 units remaining) + [ (Pair {} { Elt "foo" 0 } (Some True)) ] + - location: -1 (remaining gas: 1039986.117 units remaining) + [ (Pair {} { Elt "foo" 0 } (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"foo\" 1 } None)-\"bar\"-(Pa.fa8366e8a8.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"foo\" 1 } None)-\"bar\"-(Pa.fa8366e8a8.out" new file mode 100644 index 0000000000000000000000000000000000000000..ae65ef0f210144be291969923a62e5c1886aa911 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt \"foo\" 1 } None)-\"bar\"-(Pa.fa8366e8a8.out" @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair { Elt "foo" 1 } None)-"bar"-(Pair { Elt "foo" 1 } (Some False))] + +storage + (Pair { Elt "foo" 1 } (Some False)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039987.002 units remaining) + [ (Pair "bar" { Elt "foo" 1 } None) ] + - location: 12 (remaining gas: 1039986.922 units remaining) + [ "bar" @parameter + (Pair { Elt "foo" 1 } None) @storage ] + - location: 15 (remaining gas: 1039986.767 units remaining) + [ { Elt "foo" 1 } ] + - location: 16 (remaining gas: 1039986.687 units remaining) + [ { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: -1 (remaining gas: 1039986.642 units remaining) + [ { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: 13 (remaining gas: 1039986.642 units remaining) + [ "bar" @parameter + { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: 17 (remaining gas: 1039986.532 units remaining) + [ False + { Elt "foo" 1 } ] + - location: 18 (remaining gas: 1039986.457 units remaining) + [ (Some False) + { Elt "foo" 1 } ] + - location: 19 (remaining gas: 1039986.387 units remaining) + [ { Elt "foo" 1 } + (Some False) ] + - location: 20 (remaining gas: 1039986.312 units remaining) + [ (Pair { Elt "foo" 1 } (Some False)) ] + - location: 21 (remaining gas: 1039986.237 units remaining) + [ {} + (Pair { Elt "foo" 1 } (Some False)) ] + - location: 23 (remaining gas: 1039986.162 units remaining) + [ (Pair {} { Elt "foo" 1 } (Some False)) ] + - location: -1 (remaining gas: 1039986.117 units remaining) + [ (Pair {} { Elt "foo" 1 } (Some False)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair {} None)-\"bar\"-(Pair {} (Some False))].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair {} None)-\"bar\"-(Pair {} (Some False))].out" new file mode 100644 index 0000000000000000000000000000000000000000..d0edd16ef75b7ea196042db566f3ebfab7ce5476 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair {} None)-\"bar\"-(Pair {} (Some False))].out" @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_mem_string.tz-(Pair {} None)-"bar"-(Pair {} (Some False))] + +storage + (Pair {} (Some False)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039987.606 units remaining) + [ (Pair "bar" {} None) ] + - location: 12 (remaining gas: 1039987.526 units remaining) + [ "bar" @parameter + (Pair {} None) @storage ] + - location: 15 (remaining gas: 1039987.371 units remaining) + [ {} ] + - location: 16 (remaining gas: 1039987.291 units remaining) + [ {} + {} ] + - location: -1 (remaining gas: 1039987.246 units remaining) + [ {} + {} ] + - location: 13 (remaining gas: 1039987.246 units remaining) + [ "bar" @parameter + {} + {} ] + - location: 17 (remaining gas: 1039987.136 units remaining) + [ False + {} ] + - location: 18 (remaining gas: 1039987.061 units remaining) + [ (Some False) + {} ] + - location: 19 (remaining gas: 1039986.991 units remaining) + [ {} + (Some False) ] + - location: 20 (remaining gas: 1039986.916 units remaining) + [ (Pair {} (Some False)) ] + - location: 21 (remaining gas: 1039986.841 units remaining) + [ {} + (Pair {} (Some False)) ] + - location: 23 (remaining gas: 1039986.766 units remaining) + [ (Pair {} {} (Some False)) ] + - location: -1 (remaining gas: 1039986.721 units remaining) + [ (Pair {} {} (Some False)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt \"a\" 1 ; Elt \"b\" 2 ; Elt \"c\" 3 ; .1da2c2c3fa.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt \"a\" 1 ; Elt \"b\" 2 ; Elt \"c\" 3 ; .1da2c2c3fa.out" new file mode 100644 index 0000000000000000000000000000000000000000..268e65c0157e94317616fd49ac12b1aa2db50b63 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt \"a\" 1 ; Elt \"b\" 2 ; Elt \"c\" 3 ; .1da2c2c3fa.out" @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 ; Elt "d" 4 ; Elt "e" 5 ; Elt "f" 6 }-6] + +storage + 6 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039990.296 units remaining) + [ (Pair { Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 ; Elt "d" 4 ; Elt "e" 5 ; Elt "f" 6 } 111) ] + - location: 9 (remaining gas: 1039990.216 units remaining) + [ { Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 ; Elt "d" 4 ; Elt "e" 5 ; Elt "f" 6 } @parameter ] + - location: 10 (remaining gas: 1039990.136 units remaining) + [ 6 ] + - location: 11 (remaining gas: 1039990.061 units remaining) + [ {} + 6 ] + - location: 13 (remaining gas: 1039989.986 units remaining) + [ (Pair {} 6) ] + - location: -1 (remaining gas: 1039989.941 units remaining) + [ (Pair {} 6) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt \"a\" 1 ; Elt \"b\" 2 ; Elt \"c\" 3 }-3].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt \"a\" 1 ; Elt \"b\" 2 ; Elt \"c\" 3 }-3].out" new file mode 100644 index 0000000000000000000000000000000000000000..9423b90bad2f61e5ea88d670926d80f5bce6df6c --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt \"a\" 1 ; Elt \"b\" 2 ; Elt \"c\" 3 }-3].out" @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 }-3] + +storage + 3 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.408 units remaining) + [ (Pair { Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 } 111) ] + - location: 9 (remaining gas: 1039992.328 units remaining) + [ { Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 } @parameter ] + - location: 10 (remaining gas: 1039992.248 units remaining) + [ 3 ] + - location: 11 (remaining gas: 1039992.173 units remaining) + [ {} + 3 ] + - location: 13 (remaining gas: 1039992.098 units remaining) + [ (Pair {} 3) ] + - location: -1 (remaining gas: 1039992.053 units remaining) + [ (Pair {} 3) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt \"a\" 1 }-1].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt \"a\" 1 }-1].out" new file mode 100644 index 0000000000000000000000000000000000000000..c2609e82913a60f76ca61be45cee03a0b126cf7f --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt \"a\" 1 }-1].out" @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_size.tz-111-{ Elt "a" 1 }-1] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.816 units remaining) + [ (Pair { Elt "a" 1 } 111) ] + - location: 9 (remaining gas: 1039993.736 units remaining) + [ { Elt "a" 1 } @parameter ] + - location: 10 (remaining gas: 1039993.656 units remaining) + [ 1 ] + - location: 11 (remaining gas: 1039993.581 units remaining) + [ {} + 1 ] + - location: 13 (remaining gas: 1039993.506 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039993.461 units remaining) + [ (Pair {} 1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{}-0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{}-0].out new file mode 100644 index 0000000000000000000000000000000000000000..c6abe6e9b22fcf48603d15fd715593d2d312854c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[map_size.tz-111-{}-0].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[map_size.tz-111-{}-0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039994.400 units remaining) + [ (Pair {} 111) ] + - location: 9 (remaining gas: 1039994.320 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039994.240 units remaining) + [ 0 ] + - location: 11 (remaining gas: 1039994.165 units remaining) + [ {} + 0 ] + - location: 13 (remaining gas: 1039994.090 units remaining) + [ (Pair {} 0) ] + - location: -1 (remaining gas: 1039994.045 units remaining) + [ (Pair {} 0) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[mul.tz-Unit-Unit-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[mul.tz-Unit-Unit-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..8be90766c1690d8506410e04a910ce158df3080d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[mul.tz-Unit-Unit-Unit].out @@ -0,0 +1,133 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[mul.tz-Unit-Unit-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039937.860 units remaining) + [ (Pair Unit Unit) ] + - location: 7 (remaining gas: 1039937.780 units remaining) + [ Unit @parameter ] + - location: 8 (remaining gas: 1039937.705 units remaining) + [ ] + - location: 9 (remaining gas: 1039937.630 units remaining) + [ 7987 ] + - location: 12 (remaining gas: 1039937.555 units remaining) + [ 10 + 7987 ] + - location: 15 (remaining gas: 1039937.059 units remaining) + [ 79870 ] + - location: 16 (remaining gas: 1039936.984 units remaining) + [ 79870 + 79870 ] + - location: 19 (remaining gas: 1039936.850 units remaining) + [ 0 ] + - location: 21 (remaining gas: 1039936.745 units remaining) + [ True ] + - location: 23 (remaining gas: 1039936.645 units remaining) + [ ] + - location: -1 (remaining gas: 1039936.600 units remaining) + [ ] + - location: 28 (remaining gas: 1039936.525 units remaining) + [ 10 ] + - location: 31 (remaining gas: 1039936.450 units remaining) + [ 7987 + 10 ] + - location: 34 (remaining gas: 1039935.954 units remaining) + [ 79870 ] + - location: 35 (remaining gas: 1039935.879 units remaining) + [ 79870 + 79870 ] + - location: 38 (remaining gas: 1039935.745 units remaining) + [ 0 ] + - location: 40 (remaining gas: 1039935.640 units remaining) + [ True ] + - location: 42 (remaining gas: 1039935.540 units remaining) + [ ] + - location: -1 (remaining gas: 1039935.495 units remaining) + [ ] + - location: 47 (remaining gas: 1039935.420 units remaining) + [ 10 ] + - location: 50 (remaining gas: 1039935.345 units remaining) + [ -7987 + 10 ] + - location: 53 (remaining gas: 1039935.226 units remaining) + [ -79870 ] + - location: 54 (remaining gas: 1039935.151 units remaining) + [ -79870 + -79870 ] + - location: 57 (remaining gas: 1039934.971 units remaining) + [ 0 ] + - location: 59 (remaining gas: 1039934.866 units remaining) + [ True ] + - location: 61 (remaining gas: 1039934.766 units remaining) + [ ] + - location: -1 (remaining gas: 1039934.721 units remaining) + [ ] + - location: 66 (remaining gas: 1039934.646 units remaining) + [ 10 ] + - location: 69 (remaining gas: 1039934.571 units remaining) + [ -7987 + 10 ] + - location: 72 (remaining gas: 1039934.452 units remaining) + [ -79870 ] + - location: 73 (remaining gas: 1039934.377 units remaining) + [ -79870 + -79870 ] + - location: 76 (remaining gas: 1039934.197 units remaining) + [ 0 ] + - location: 78 (remaining gas: 1039934.092 units remaining) + [ True ] + - location: 80 (remaining gas: 1039933.992 units remaining) + [ ] + - location: -1 (remaining gas: 1039933.947 units remaining) + [ ] + - location: 85 (remaining gas: 1039933.872 units remaining) + [ -10 ] + - location: 88 (remaining gas: 1039933.797 units remaining) + [ 7987 + -10 ] + - location: 91 (remaining gas: 1039933.678 units remaining) + [ -79870 ] + - location: 92 (remaining gas: 1039933.603 units remaining) + [ -79870 + -79870 ] + - location: 95 (remaining gas: 1039933.423 units remaining) + [ 0 ] + - location: 97 (remaining gas: 1039933.318 units remaining) + [ True ] + - location: 99 (remaining gas: 1039933.218 units remaining) + [ ] + - location: -1 (remaining gas: 1039933.173 units remaining) + [ ] + - location: 104 (remaining gas: 1039933.098 units remaining) + [ 10 ] + - location: 107 (remaining gas: 1039933.023 units remaining) + [ 7987 + 10 ] + - location: 110 (remaining gas: 1039932.904 units remaining) + [ 79870 ] + - location: 111 (remaining gas: 1039932.829 units remaining) + [ 79870 + 79870 ] + - location: 114 (remaining gas: 1039932.649 units remaining) + [ 0 ] + - location: 116 (remaining gas: 1039932.544 units remaining) + [ True ] + - location: 118 (remaining gas: 1039932.444 units remaining) + [ ] + - location: -1 (remaining gas: 1039932.399 units remaining) + [ ] + - location: 123 (remaining gas: 1039932.324 units remaining) + [ Unit ] + - location: 124 (remaining gas: 1039932.249 units remaining) + [ {} + Unit ] + - location: 126 (remaining gas: 1039932.174 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039932.129 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[mutez_to_bls12_381_fr.tz-0x00-257-0x0101000000000000000.be11332c7f.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[mutez_to_bls12_381_fr.tz-0x00-257-0x0101000000000000000.be11332c7f.out new file mode 100644 index 0000000000000000000000000000000000000000..abc26fefc5372866de9c4c6a9dba3b4a6577bee6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[mutez_to_bls12_381_fr.tz-0x00-257-0x0101000000000000000.be11332c7f.out @@ -0,0 +1,40 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[mutez_to_bls12_381_fr.tz-0x00-257-0x0101000000000000000000000000000000000000000000000000000000000000] + +storage + 0x0101000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039986.695 units remaining) + [ (Pair 257 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039986.615 units remaining) + [ 257 @parameter ] + - location: 8 (remaining gas: 1039986.540 units remaining) + [ 1 + 257 @parameter ] + - location: 11 (remaining gas: 1039986.470 units remaining) + [ 257 @parameter + 1 ] + - location: 12 (remaining gas: 1039986.240 units remaining) + [ (Some (Pair 257 0)) ] + - location: 19 (remaining gas: 1039986.105 units remaining) + [ (Pair 257 0) @some ] + - location: 13 (remaining gas: 1039986.060 units remaining) + [ (Pair 257 0) @some ] + - location: 20 (remaining gas: 1039985.980 units remaining) + [ 257 ] + - location: 21 (remaining gas: 1039985.905 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 257 ] + - location: 24 (remaining gas: 1039985.495 units remaining) + [ 0x0101000000000000000000000000000000000000000000000000000000000000 ] + - location: 25 (remaining gas: 1039985.420 units remaining) + [ {} + 0x0101000000000000000000000000000000000000000000000000000000000000 ] + - location: 27 (remaining gas: 1039985.345 units remaining) + [ (Pair {} 0x0101000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039985.300 units remaining) + [ (Pair {} 0x0101000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[mutez_to_bls12_381_fr.tz-0x02-16-0x10000000000000000000.8230fb4fac.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[mutez_to_bls12_381_fr.tz-0x02-16-0x10000000000000000000.8230fb4fac.out new file mode 100644 index 0000000000000000000000000000000000000000..e32a6511ea74f6962fe1f934382127222968f6b8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[mutez_to_bls12_381_fr.tz-0x02-16-0x10000000000000000000.8230fb4fac.out @@ -0,0 +1,40 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[mutez_to_bls12_381_fr.tz-0x02-16-0x1000000000000000000000000000000000000000000000000000000000000000] + +storage + 0x1000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039986.695 units remaining) + [ (Pair 16 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (remaining gas: 1039986.615 units remaining) + [ 16 @parameter ] + - location: 8 (remaining gas: 1039986.540 units remaining) + [ 1 + 16 @parameter ] + - location: 11 (remaining gas: 1039986.470 units remaining) + [ 16 @parameter + 1 ] + - location: 12 (remaining gas: 1039986.240 units remaining) + [ (Some (Pair 16 0)) ] + - location: 19 (remaining gas: 1039986.105 units remaining) + [ (Pair 16 0) @some ] + - location: 13 (remaining gas: 1039986.060 units remaining) + [ (Pair 16 0) @some ] + - location: 20 (remaining gas: 1039985.980 units remaining) + [ 16 ] + - location: 21 (remaining gas: 1039985.905 units remaining) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 16 ] + - location: 24 (remaining gas: 1039985.495 units remaining) + [ 0x1000000000000000000000000000000000000000000000000000000000000000 ] + - location: 25 (remaining gas: 1039985.420 units remaining) + [ {} + 0x1000000000000000000000000000000000000000000000000000000000000000 ] + - location: 27 (remaining gas: 1039985.345 units remaining) + [ (Pair {} 0x1000000000000000000000000000000000000000000000000000000000000000) ] + - location: -1 (remaining gas: 1039985.300 units remaining) + [ (Pair {} 0x1000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left -2)-2].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left -2)-2].out new file mode 100644 index 0000000000000000000000000000000000000000..a10dec654db2b1921323b9c6f4b03e67f0e8e5a8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left -2)-2].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left -2)-2] + +storage + 2 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.530 units remaining) + [ (Pair (Left -2) 0) ] + - location: 9 (remaining gas: 1039992.450 units remaining) + [ (Left -2) @parameter ] + - location: 12 (remaining gas: 1039992.280 units remaining) + [ 2 ] + - location: 11 (remaining gas: 1039992.235 units remaining) + [ 2 ] + - location: 15 (remaining gas: 1039992.160 units remaining) + [ {} + 2 ] + - location: 17 (remaining gas: 1039992.085 units remaining) + [ (Pair {} 2) ] + - location: -1 (remaining gas: 1039992.040 units remaining) + [ (Pair {} 2) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left 0)-0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left 0)-0].out new file mode 100644 index 0000000000000000000000000000000000000000..f92bb00bbf848813ac2378a320fecd84a562e37f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left 0)-0].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left 0)-0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.530 units remaining) + [ (Pair (Left 0) 0) ] + - location: 9 (remaining gas: 1039992.450 units remaining) + [ (Left 0) @parameter ] + - location: 12 (remaining gas: 1039992.280 units remaining) + [ 0 ] + - location: 11 (remaining gas: 1039992.235 units remaining) + [ 0 ] + - location: 15 (remaining gas: 1039992.160 units remaining) + [ {} + 0 ] + - location: 17 (remaining gas: 1039992.085 units remaining) + [ (Pair {} 0) ] + - location: -1 (remaining gas: 1039992.040 units remaining) + [ (Pair {} 0) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left 2)--2].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left 2)--2].out new file mode 100644 index 0000000000000000000000000000000000000000..c8983758de7595926c585d6fb5e77dbe99c16917 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left 2)--2].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[neg.tz-0-(Left 2)--2] + +storage + -2 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.530 units remaining) + [ (Pair (Left 2) 0) ] + - location: 9 (remaining gas: 1039992.450 units remaining) + [ (Left 2) @parameter ] + - location: 12 (remaining gas: 1039992.280 units remaining) + [ -2 ] + - location: 11 (remaining gas: 1039992.235 units remaining) + [ -2 ] + - location: 15 (remaining gas: 1039992.160 units remaining) + [ {} + -2 ] + - location: 17 (remaining gas: 1039992.085 units remaining) + [ (Pair {} -2) ] + - location: -1 (remaining gas: 1039992.040 units remaining) + [ (Pair {} -2) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Right 0)-0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Right 0)-0].out new file mode 100644 index 0000000000000000000000000000000000000000..a34d230215042747134107e785294c344600c28a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Right 0)-0].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[neg.tz-0-(Right 0)-0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.530 units remaining) + [ (Pair (Right 0) 0) ] + - location: 9 (remaining gas: 1039992.450 units remaining) + [ (Right 0) @parameter ] + - location: 14 (remaining gas: 1039992.280 units remaining) + [ 0 ] + - location: 13 (remaining gas: 1039992.235 units remaining) + [ 0 ] + - location: 15 (remaining gas: 1039992.160 units remaining) + [ {} + 0 ] + - location: 17 (remaining gas: 1039992.085 units remaining) + [ (Pair {} 0) ] + - location: -1 (remaining gas: 1039992.040 units remaining) + [ (Pair {} 0) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Right 2)--2].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Right 2)--2].out new file mode 100644 index 0000000000000000000000000000000000000000..f8ee5ed665e5ae9f6d7547b4118a15f8b1a8c383 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[neg.tz-0-(Right 2)--2].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[neg.tz-0-(Right 2)--2] + +storage + -2 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039992.530 units remaining) + [ (Pair (Right 2) 0) ] + - location: 9 (remaining gas: 1039992.450 units remaining) + [ (Right 2) @parameter ] + - location: 14 (remaining gas: 1039992.280 units remaining) + [ -2 ] + - location: 13 (remaining gas: 1039992.235 units remaining) + [ -2 ] + - location: 15 (remaining gas: 1039992.160 units remaining) + [ {} + -2 ] + - location: 17 (remaining gas: 1039992.085 units remaining) + [ (Pair {} -2) ] + - location: -1 (remaining gas: 1039992.040 units remaining) + [ (Pair {} -2) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[none.tz-Some 10-Unit-None].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[none.tz-Some 10-Unit-None].out new file mode 100644 index 0000000000000000000000000000000000000000..3c287d2278adb6510123fe2a664dbbd45c3d9ed3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[none.tz-Some 10-Unit-None].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[none.tz-Some 10-Unit-None] + +storage + None +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.030 units remaining) + [ (Pair Unit (Some 10)) ] + - location: 8 (remaining gas: 1039993.955 units remaining) + [ ] + - location: 9 (remaining gas: 1039993.880 units remaining) + [ None ] + - location: 11 (remaining gas: 1039993.805 units remaining) + [ {} + None ] + - location: 13 (remaining gas: 1039993.730 units remaining) + [ (Pair {} None) ] + - location: -1 (remaining gas: 1039993.685 units remaining) + [ (Pair {} None) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not.tz-None-False-(Some True)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not.tz-None-False-(Some True)].out new file mode 100644 index 0000000000000000000000000000000000000000..546b451e0c9401249af77b3023e326607f0eb317 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not.tz-None-False-(Some True)].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not.tz-None-False-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.690 units remaining) + [ (Pair False None) ] + - location: 8 (remaining gas: 1039993.610 units remaining) + [ False @parameter ] + - location: 9 (remaining gas: 1039993.530 units remaining) + [ True ] + - location: 10 (remaining gas: 1039993.455 units remaining) + [ (Some True) ] + - location: 11 (remaining gas: 1039993.380 units remaining) + [ {} + (Some True) ] + - location: 13 (remaining gas: 1039993.305 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039993.260 units remaining) + [ (Pair {} (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not.tz-None-True-(Some False)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not.tz-None-True-(Some False)].out new file mode 100644 index 0000000000000000000000000000000000000000..96302d9c625397fa83af4506f754b405aecdbe72 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not.tz-None-True-(Some False)].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not.tz-None-True-(Some False)] + +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.690 units remaining) + [ (Pair True None) ] + - location: 8 (remaining gas: 1039993.610 units remaining) + [ True @parameter ] + - location: 9 (remaining gas: 1039993.530 units remaining) + [ False ] + - location: 10 (remaining gas: 1039993.455 units remaining) + [ (Some False) ] + - location: 11 (remaining gas: 1039993.380 units remaining) + [ {} + (Some False) ] + - location: 13 (remaining gas: 1039993.305 units remaining) + [ (Pair {} (Some False)) ] + - location: -1 (remaining gas: 1039993.260 units remaining) + [ (Pair {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left -8)-(Some 7)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left -8)-(Some 7)].out new file mode 100644 index 0000000000000000000000000000000000000000..03eeba98ae4cecbc2c026ba4e340f1cc175a9bdc --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left -8)-(Some 7)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left -8)-(Some 7)] + +storage + (Some 7) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039991.480 units remaining) + [ (Pair (Left -8) None) ] + - location: 10 (remaining gas: 1039991.400 units remaining) + [ (Left -8) @parameter ] + - location: 13 (remaining gas: 1039991.255 units remaining) + [ 7 ] + - location: 12 (remaining gas: 1039991.210 units remaining) + [ 7 ] + - location: 16 (remaining gas: 1039991.135 units remaining) + [ (Some 7) ] + - location: 17 (remaining gas: 1039991.060 units remaining) + [ {} + (Some 7) ] + - location: 19 (remaining gas: 1039990.985 units remaining) + [ (Pair {} (Some 7)) ] + - location: -1 (remaining gas: 1039990.940 units remaining) + [ (Pair {} (Some 7)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left -9)-(Some 8)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left -9)-(Some 8)].out new file mode 100644 index 0000000000000000000000000000000000000000..04d5943339c9853e4e5be52579fed094af6d9a14 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left -9)-(Some 8)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left -9)-(Some 8)] + +storage + (Some 8) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039991.480 units remaining) + [ (Pair (Left -9) None) ] + - location: 10 (remaining gas: 1039991.400 units remaining) + [ (Left -9) @parameter ] + - location: 13 (remaining gas: 1039991.255 units remaining) + [ 8 ] + - location: 12 (remaining gas: 1039991.210 units remaining) + [ 8 ] + - location: 16 (remaining gas: 1039991.135 units remaining) + [ (Some 8) ] + - location: 17 (remaining gas: 1039991.060 units remaining) + [ {} + (Some 8) ] + - location: 19 (remaining gas: 1039990.985 units remaining) + [ (Pair {} (Some 8)) ] + - location: -1 (remaining gas: 1039990.940 units remaining) + [ (Pair {} (Some 8)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 0)-(Some -1)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 0)-(Some -1)].out new file mode 100644 index 0000000000000000000000000000000000000000..b2f1b49719edae6421bf93005da670f36ac296a4 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 0)-(Some -1)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 0)-(Some -1)] + +storage + (Some -1) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039991.480 units remaining) + [ (Pair (Left 0) None) ] + - location: 10 (remaining gas: 1039991.400 units remaining) + [ (Left 0) @parameter ] + - location: 13 (remaining gas: 1039991.255 units remaining) + [ -1 ] + - location: 12 (remaining gas: 1039991.210 units remaining) + [ -1 ] + - location: 16 (remaining gas: 1039991.135 units remaining) + [ (Some -1) ] + - location: 17 (remaining gas: 1039991.060 units remaining) + [ {} + (Some -1) ] + - location: 19 (remaining gas: 1039990.985 units remaining) + [ (Pair {} (Some -1)) ] + - location: -1 (remaining gas: 1039990.940 units remaining) + [ (Pair {} (Some -1)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 7)-(Some -8)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 7)-(Some -8)].out new file mode 100644 index 0000000000000000000000000000000000000000..7ad4b4282881b680f39d02266d58148bd4f62e2b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 7)-(Some -8)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 7)-(Some -8)] + +storage + (Some -8) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039991.480 units remaining) + [ (Pair (Left 7) None) ] + - location: 10 (remaining gas: 1039991.400 units remaining) + [ (Left 7) @parameter ] + - location: 13 (remaining gas: 1039991.255 units remaining) + [ -8 ] + - location: 12 (remaining gas: 1039991.210 units remaining) + [ -8 ] + - location: 16 (remaining gas: 1039991.135 units remaining) + [ (Some -8) ] + - location: 17 (remaining gas: 1039991.060 units remaining) + [ {} + (Some -8) ] + - location: 19 (remaining gas: 1039990.985 units remaining) + [ (Pair {} (Some -8)) ] + - location: -1 (remaining gas: 1039990.940 units remaining) + [ (Pair {} (Some -8)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 8)-(Some -9)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 8)-(Some -9)].out new file mode 100644 index 0000000000000000000000000000000000000000..238e1b4028cc0bba5919445e4c6c54a641153410 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 8)-(Some -9)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Left 8)-(Some -9)] + +storage + (Some -9) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039991.480 units remaining) + [ (Pair (Left 8) None) ] + - location: 10 (remaining gas: 1039991.400 units remaining) + [ (Left 8) @parameter ] + - location: 13 (remaining gas: 1039991.255 units remaining) + [ -9 ] + - location: 12 (remaining gas: 1039991.210 units remaining) + [ -9 ] + - location: 16 (remaining gas: 1039991.135 units remaining) + [ (Some -9) ] + - location: 17 (remaining gas: 1039991.060 units remaining) + [ {} + (Some -9) ] + - location: 19 (remaining gas: 1039990.985 units remaining) + [ (Pair {} (Some -9)) ] + - location: -1 (remaining gas: 1039990.940 units remaining) + [ (Pair {} (Some -9)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 0)-(Some -1)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 0)-(Some -1)].out new file mode 100644 index 0000000000000000000000000000000000000000..4d0848ba9c83fe0f7a440359323e1e8c28a1f51b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 0)-(Some -1)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 0)-(Some -1)] + +storage + (Some -1) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039991.480 units remaining) + [ (Pair (Right 0) None) ] + - location: 10 (remaining gas: 1039991.400 units remaining) + [ (Right 0) @parameter ] + - location: 15 (remaining gas: 1039991.255 units remaining) + [ -1 ] + - location: 14 (remaining gas: 1039991.210 units remaining) + [ -1 ] + - location: 16 (remaining gas: 1039991.135 units remaining) + [ (Some -1) ] + - location: 17 (remaining gas: 1039991.060 units remaining) + [ {} + (Some -1) ] + - location: 19 (remaining gas: 1039990.985 units remaining) + [ (Pair {} (Some -1)) ] + - location: -1 (remaining gas: 1039990.940 units remaining) + [ (Pair {} (Some -1)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 7)-(Some -8)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 7)-(Some -8)].out new file mode 100644 index 0000000000000000000000000000000000000000..37ea550552299fe5084115d0fce3fa8e64f8e206 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 7)-(Some -8)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 7)-(Some -8)] + +storage + (Some -8) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039991.480 units remaining) + [ (Pair (Right 7) None) ] + - location: 10 (remaining gas: 1039991.400 units remaining) + [ (Right 7) @parameter ] + - location: 15 (remaining gas: 1039991.255 units remaining) + [ -8 ] + - location: 14 (remaining gas: 1039991.210 units remaining) + [ -8 ] + - location: 16 (remaining gas: 1039991.135 units remaining) + [ (Some -8) ] + - location: 17 (remaining gas: 1039991.060 units remaining) + [ {} + (Some -8) ] + - location: 19 (remaining gas: 1039990.985 units remaining) + [ (Pair {} (Some -8)) ] + - location: -1 (remaining gas: 1039990.940 units remaining) + [ (Pair {} (Some -8)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 8)-(Some -9)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 8)-(Some -9)].out new file mode 100644 index 0000000000000000000000000000000000000000..05eeffda229d03ca8b6bdf320045fa0acd3b39d6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 8)-(Some -9)].out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[not_binary.tz-None-(Right 8)-(Some -9)] + +storage + (Some -9) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039991.480 units remaining) + [ (Pair (Right 8) None) ] + - location: 10 (remaining gas: 1039991.400 units remaining) + [ (Right 8) @parameter ] + - location: 15 (remaining gas: 1039991.255 units remaining) + [ -9 ] + - location: 14 (remaining gas: 1039991.210 units remaining) + [ -9 ] + - location: 16 (remaining gas: 1039991.135 units remaining) + [ (Some -9) ] + - location: 17 (remaining gas: 1039991.060 units remaining) + [ {} + (Some -9) ] + - location: 19 (remaining gas: 1039990.985 units remaining) + [ (Pair {} (Some -9)) ] + - location: -1 (remaining gas: 1039990.940 units remaining) + [ (Pair {} (Some -9)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair False False)-(Some False)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair False False)-(Some False)].out new file mode 100644 index 0000000000000000000000000000000000000000..48ed2a8d83f693303e5746bcbe461614e01ad13c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair False False)-(Some False)].out @@ -0,0 +1,37 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair False False)-(Some False)] + +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.150 units remaining) + [ (Pair (Pair False False) None) ] + - location: 10 (remaining gas: 1039989.070 units remaining) + [ (Pair False False) @parameter ] + - location: 11 (remaining gas: 1039988.990 units remaining) + [ (Pair False False) @parameter + (Pair False False) @parameter ] + - location: 12 (remaining gas: 1039988.910 units remaining) + [ False + (Pair False False) @parameter ] + - location: 13 (remaining gas: 1039988.840 units remaining) + [ (Pair False False) @parameter + False ] + - location: 14 (remaining gas: 1039988.760 units remaining) + [ False + False ] + - location: 15 (remaining gas: 1039988.680 units remaining) + [ False ] + - location: 16 (remaining gas: 1039988.605 units remaining) + [ (Some False) ] + - location: 17 (remaining gas: 1039988.530 units remaining) + [ {} + (Some False) ] + - location: 19 (remaining gas: 1039988.455 units remaining) + [ (Pair {} (Some False)) ] + - location: -1 (remaining gas: 1039988.410 units remaining) + [ (Pair {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair False True)-(Some True)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair False True)-(Some True)].out new file mode 100644 index 0000000000000000000000000000000000000000..a89f3124092caf82b61d696fedc31618f69fd654 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair False True)-(Some True)].out @@ -0,0 +1,37 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair False True)-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.150 units remaining) + [ (Pair (Pair False True) None) ] + - location: 10 (remaining gas: 1039989.070 units remaining) + [ (Pair False True) @parameter ] + - location: 11 (remaining gas: 1039988.990 units remaining) + [ (Pair False True) @parameter + (Pair False True) @parameter ] + - location: 12 (remaining gas: 1039988.910 units remaining) + [ False + (Pair False True) @parameter ] + - location: 13 (remaining gas: 1039988.840 units remaining) + [ (Pair False True) @parameter + False ] + - location: 14 (remaining gas: 1039988.760 units remaining) + [ True + False ] + - location: 15 (remaining gas: 1039988.680 units remaining) + [ True ] + - location: 16 (remaining gas: 1039988.605 units remaining) + [ (Some True) ] + - location: 17 (remaining gas: 1039988.530 units remaining) + [ {} + (Some True) ] + - location: 19 (remaining gas: 1039988.455 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039988.410 units remaining) + [ (Pair {} (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair True False)-(Some True)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair True False)-(Some True)].out new file mode 100644 index 0000000000000000000000000000000000000000..533d71f6037392bd391ef5421ee224cd3be285d4 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair True False)-(Some True)].out @@ -0,0 +1,37 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair True False)-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.150 units remaining) + [ (Pair (Pair True False) None) ] + - location: 10 (remaining gas: 1039989.070 units remaining) + [ (Pair True False) @parameter ] + - location: 11 (remaining gas: 1039988.990 units remaining) + [ (Pair True False) @parameter + (Pair True False) @parameter ] + - location: 12 (remaining gas: 1039988.910 units remaining) + [ True + (Pair True False) @parameter ] + - location: 13 (remaining gas: 1039988.840 units remaining) + [ (Pair True False) @parameter + True ] + - location: 14 (remaining gas: 1039988.760 units remaining) + [ False + True ] + - location: 15 (remaining gas: 1039988.680 units remaining) + [ True ] + - location: 16 (remaining gas: 1039988.605 units remaining) + [ (Some True) ] + - location: 17 (remaining gas: 1039988.530 units remaining) + [ {} + (Some True) ] + - location: 19 (remaining gas: 1039988.455 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039988.410 units remaining) + [ (Pair {} (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair True True)-(Some True)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair True True)-(Some True)].out new file mode 100644 index 0000000000000000000000000000000000000000..9a0b0d82e1a80e39641bd1993a59a3204e19f977 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair True True)-(Some True)].out @@ -0,0 +1,37 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or.tz-None-(Pair True True)-(Some True)] + +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039989.150 units remaining) + [ (Pair (Pair True True) None) ] + - location: 10 (remaining gas: 1039989.070 units remaining) + [ (Pair True True) @parameter ] + - location: 11 (remaining gas: 1039988.990 units remaining) + [ (Pair True True) @parameter + (Pair True True) @parameter ] + - location: 12 (remaining gas: 1039988.910 units remaining) + [ True + (Pair True True) @parameter ] + - location: 13 (remaining gas: 1039988.840 units remaining) + [ (Pair True True) @parameter + True ] + - location: 14 (remaining gas: 1039988.760 units remaining) + [ True + True ] + - location: 15 (remaining gas: 1039988.680 units remaining) + [ True ] + - location: 16 (remaining gas: 1039988.605 units remaining) + [ (Some True) ] + - location: 17 (remaining gas: 1039988.530 units remaining) + [ {} + (Some True) ] + - location: 19 (remaining gas: 1039988.455 units remaining) + [ (Pair {} (Some True)) ] + - location: -1 (remaining gas: 1039988.410 units remaining) + [ (Pair {} (Some True)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 0 8)-(Some 8)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 0 8)-(Some 8)].out new file mode 100644 index 0000000000000000000000000000000000000000..f69e62d190ae9f59a4ef97840dff508f09e39578 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 0 8)-(Some 8)].out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 0 8)-(Some 8)] + +storage + (Some 8) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.120 units remaining) + [ (Pair (Pair 0 8) None) ] + - location: 10 (remaining gas: 1039992.040 units remaining) + [ (Pair 0 8) @parameter ] + - location: 11 (remaining gas: 1039991.960 units remaining) + [ 0 + 8 ] + - location: 12 (remaining gas: 1039991.850 units remaining) + [ 8 ] + - location: 13 (remaining gas: 1039991.775 units remaining) + [ (Some 8) ] + - location: 14 (remaining gas: 1039991.700 units remaining) + [ {} + (Some 8) ] + - location: 16 (remaining gas: 1039991.625 units remaining) + [ (Pair {} (Some 8)) ] + - location: -1 (remaining gas: 1039991.580 units remaining) + [ (Pair {} (Some 8)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 14 1)-(Some 15)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 14 1)-(Some 15)].out new file mode 100644 index 0000000000000000000000000000000000000000..e91b692b625d6471bd3585f4de40a3dbd1b6101d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 14 1)-(Some 15)].out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 14 1)-(Some 15)] + +storage + (Some 15) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.120 units remaining) + [ (Pair (Pair 14 1) None) ] + - location: 10 (remaining gas: 1039992.040 units remaining) + [ (Pair 14 1) @parameter ] + - location: 11 (remaining gas: 1039991.960 units remaining) + [ 14 + 1 ] + - location: 12 (remaining gas: 1039991.850 units remaining) + [ 15 ] + - location: 13 (remaining gas: 1039991.775 units remaining) + [ (Some 15) ] + - location: 14 (remaining gas: 1039991.700 units remaining) + [ {} + (Some 15) ] + - location: 16 (remaining gas: 1039991.625 units remaining) + [ (Pair {} (Some 15)) ] + - location: -1 (remaining gas: 1039991.580 units remaining) + [ (Pair {} (Some 15)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 15 4)-(Some 15)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 15 4)-(Some 15)].out new file mode 100644 index 0000000000000000000000000000000000000000..829c29df6f620980ccbd5142b8497d0d1ecd0771 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 15 4)-(Some 15)].out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 15 4)-(Some 15)] + +storage + (Some 15) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.120 units remaining) + [ (Pair (Pair 15 4) None) ] + - location: 10 (remaining gas: 1039992.040 units remaining) + [ (Pair 15 4) @parameter ] + - location: 11 (remaining gas: 1039991.960 units remaining) + [ 15 + 4 ] + - location: 12 (remaining gas: 1039991.850 units remaining) + [ 15 ] + - location: 13 (remaining gas: 1039991.775 units remaining) + [ (Some 15) ] + - location: 14 (remaining gas: 1039991.700 units remaining) + [ {} + (Some 15) ] + - location: 16 (remaining gas: 1039991.625 units remaining) + [ (Pair {} (Some 15)) ] + - location: -1 (remaining gas: 1039991.580 units remaining) + [ (Pair {} (Some 15)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 4 8)-(Some 12)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 4 8)-(Some 12)].out new file mode 100644 index 0000000000000000000000000000000000000000..21778eeff43a480d108667ecbda0de15029d5b7a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 4 8)-(Some 12)].out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 4 8)-(Some 12)] + +storage + (Some 12) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.120 units remaining) + [ (Pair (Pair 4 8) None) ] + - location: 10 (remaining gas: 1039992.040 units remaining) + [ (Pair 4 8) @parameter ] + - location: 11 (remaining gas: 1039991.960 units remaining) + [ 4 + 8 ] + - location: 12 (remaining gas: 1039991.850 units remaining) + [ 12 ] + - location: 13 (remaining gas: 1039991.775 units remaining) + [ (Some 12) ] + - location: 14 (remaining gas: 1039991.700 units remaining) + [ {} + (Some 12) ] + - location: 16 (remaining gas: 1039991.625 units remaining) + [ (Pair {} (Some 12)) ] + - location: -1 (remaining gas: 1039991.580 units remaining) + [ (Pair {} (Some 12)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 7 7)-(Some 7)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 7 7)-(Some 7)].out new file mode 100644 index 0000000000000000000000000000000000000000..156f39f66d4716f946827100d4f85cc644d2f0a1 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 7 7)-(Some 7)].out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 7 7)-(Some 7)] + +storage + (Some 7) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.120 units remaining) + [ (Pair (Pair 7 7) None) ] + - location: 10 (remaining gas: 1039992.040 units remaining) + [ (Pair 7 7) @parameter ] + - location: 11 (remaining gas: 1039991.960 units remaining) + [ 7 + 7 ] + - location: 12 (remaining gas: 1039991.850 units remaining) + [ 7 ] + - location: 13 (remaining gas: 1039991.775 units remaining) + [ (Some 7) ] + - location: 14 (remaining gas: 1039991.700 units remaining) + [ {} + (Some 7) ] + - location: 16 (remaining gas: 1039991.625 units remaining) + [ (Pair {} (Some 7)) ] + - location: -1 (remaining gas: 1039991.580 units remaining) + [ (Pair {} (Some 7)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 8 0)-(Some 8)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 8 0)-(Some 8)].out new file mode 100644 index 0000000000000000000000000000000000000000..85c0e54701204e99c654b6fb1f1aa3925cb8ff07 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 8 0)-(Some 8)].out @@ -0,0 +1,28 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[or_binary.tz-None-(Pair 8 0)-(Some 8)] + +storage + (Some 8) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039992.120 units remaining) + [ (Pair (Pair 8 0) None) ] + - location: 10 (remaining gas: 1039992.040 units remaining) + [ (Pair 8 0) @parameter ] + - location: 11 (remaining gas: 1039991.960 units remaining) + [ 8 + 0 ] + - location: 12 (remaining gas: 1039991.850 units remaining) + [ 8 ] + - location: 13 (remaining gas: 1039991.775 units remaining) + [ (Some 8) ] + - location: 14 (remaining gas: 1039991.700 units remaining) + [ {} + (Some 8) ] + - location: 16 (remaining gas: 1039991.625 units remaining) + [ (Pair {} (Some 8)) ] + - location: -1 (remaining gas: 1039991.580 units remaining) + [ (Pair {} (Some 8)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev.tz-Unit-(Pair -1 (Pair 1 (Pair \"foobar\".368bdfd73a.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev.tz-Unit-(Pair -1 (Pair 1 (Pair \"foobar\".368bdfd73a.out" new file mode 100644 index 0000000000000000000000000000000000000000..a33e9185d9200302cd6d492de1f3791d95071011 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev.tz-Unit-(Pair -1 (Pair 1 (Pair \"foobar\".368bdfd73a.out" @@ -0,0 +1,900 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[packunpack_rev.tz-Unit-(Pair -1 (Pair 1 (Pair "foobar" (Pair 0x00AABBCC (Pair 1000 (Pair False (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"))))))))-Unit1] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039758.056 units remaining) + [ (Pair (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + Unit) ] + - location: 16 (remaining gas: 1039757.976 units remaining) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @parameter ] + - location: 17 (remaining gas: 1039757.896 units remaining) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @parameter + (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @parameter ] + - location: 18 (remaining gas: 1039757.816 units remaining) + [ -1 + (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @parameter ] + - location: 21 (remaining gas: 1039757.661 units remaining) + [ -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 20 (remaining gas: 1039757.616 units remaining) + [ -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 19 (remaining gas: 1039757.616 units remaining) + [ -1 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 22 (remaining gas: 1039749.346 units remaining) + [ 0x050041 @packed + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 23 (remaining gas: 1039742.076 units remaining) + [ (Some -1) @packed.unpacked + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 31 (remaining gas: 1039741.941 units remaining) + [ -1 @packed.unpacked.some + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 25 (remaining gas: 1039741.896 units remaining) + [ -1 @packed.unpacked.some + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 34 (remaining gas: 1039741.656 units remaining) + [ 0 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 35 (remaining gas: 1039741.581 units remaining) + [ True + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039741.536 units remaining) + [ True + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 37 (remaining gas: 1039741.436 units remaining) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039741.391 units remaining) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 42 (remaining gas: 1039741.311 units remaining) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 43 (remaining gas: 1039741.231 units remaining) + [ 1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 46 (remaining gas: 1039741.076 units remaining) + [ 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 45 (remaining gas: 1039741.031 units remaining) + [ 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 44 (remaining gas: 1039741.031 units remaining) + [ 1 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 47 (remaining gas: 1039732.761 units remaining) + [ 0x050001 @packed + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 48 (remaining gas: 1039725.491 units remaining) + [ (Some 1) @packed.unpacked + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 56 (remaining gas: 1039725.356 units remaining) + [ 1 @packed.unpacked.some + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 50 (remaining gas: 1039725.311 units remaining) + [ 1 @packed.unpacked.some + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 59 (remaining gas: 1039725.071 units remaining) + [ 0 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 60 (remaining gas: 1039724.996 units remaining) + [ True + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039724.951 units remaining) + [ True + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 62 (remaining gas: 1039724.851 units remaining) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039724.806 units remaining) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 67 (remaining gas: 1039724.726 units remaining) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 68 (remaining gas: 1039724.646 units remaining) + [ "foobar" + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 71 (remaining gas: 1039724.491 units remaining) + [ "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 70 (remaining gas: 1039724.446 units remaining) + [ "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 69 (remaining gas: 1039724.446 units remaining) + [ "foobar" + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 72 (remaining gas: 1039712.176 units remaining) + [ 0x050100000006666f6f626172 @packed + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 73 (remaining gas: 1039704.832 units remaining) + [ (Some "foobar") @packed.unpacked + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 81 (remaining gas: 1039704.697 units remaining) + [ "foobar" @packed.unpacked.some + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 75 (remaining gas: 1039704.652 units remaining) + [ "foobar" @packed.unpacked.some + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 84 (remaining gas: 1039704.442 units remaining) + [ 0 + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 85 (remaining gas: 1039704.367 units remaining) + [ True + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039704.322 units remaining) + [ True + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 87 (remaining gas: 1039704.222 units remaining) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039704.177 units remaining) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 92 (remaining gas: 1039704.097 units remaining) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 93 (remaining gas: 1039704.017 units remaining) + [ 0x00aabbcc + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 96 (remaining gas: 1039703.862 units remaining) + [ 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 95 (remaining gas: 1039703.817 units remaining) + [ 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 94 (remaining gas: 1039703.817 units remaining) + [ 0x00aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 97 (remaining gas: 1039691.547 units remaining) + [ 0x050a0000000400aabbcc @packed + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 98 (remaining gas: 1039657.277 units remaining) + [ (Some 0x00aabbcc) @packed.unpacked + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 106 (remaining gas: 1039657.142 units remaining) + [ 0x00aabbcc @packed.unpacked.some + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 100 (remaining gas: 1039657.097 units remaining) + [ 0x00aabbcc @packed.unpacked.some + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 109 (remaining gas: 1039656.887 units remaining) + [ 0 + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 110 (remaining gas: 1039656.812 units remaining) + [ True + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039656.767 units remaining) + [ True + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 112 (remaining gas: 1039656.667 units remaining) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039656.622 units remaining) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 117 (remaining gas: 1039656.542 units remaining) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 118 (remaining gas: 1039656.462 units remaining) + [ 1000 + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 121 (remaining gas: 1039656.307 units remaining) + [ 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 120 (remaining gas: 1039656.262 units remaining) + [ 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 119 (remaining gas: 1039656.262 units remaining) + [ 1000 + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 122 (remaining gas: 1039647.992 units remaining) + [ 0x0500a80f @packed + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 123 (remaining gas: 1039640.722 units remaining) + [ (Some 1000) @packed.unpacked + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 131 (remaining gas: 1039640.587 units remaining) + [ 1000 @packed.unpacked.some + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 125 (remaining gas: 1039640.542 units remaining) + [ 1000 @packed.unpacked.some + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 134 (remaining gas: 1039640.348 units remaining) + [ 0 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 135 (remaining gas: 1039640.273 units remaining) + [ True + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039640.228 units remaining) + [ True + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 137 (remaining gas: 1039640.128 units remaining) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039640.083 units remaining) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 142 (remaining gas: 1039640.003 units remaining) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 143 (remaining gas: 1039639.923 units remaining) + [ False + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 146 (remaining gas: 1039639.768 units remaining) + [ False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 145 (remaining gas: 1039639.723 units remaining) + [ False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 144 (remaining gas: 1039639.723 units remaining) + [ False + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 147 (remaining gas: 1039631.453 units remaining) + [ 0x050303 @packed + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 148 (remaining gas: 1039624.183 units remaining) + [ (Some False) @packed.unpacked + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 156 (remaining gas: 1039624.048 units remaining) + [ False @packed.unpacked.some + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 150 (remaining gas: 1039624.003 units remaining) + [ False @packed.unpacked.some + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 159 (remaining gas: 1039623.705 units remaining) + [ 0 + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 160 (remaining gas: 1039623.630 units remaining) + [ True + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039623.585 units remaining) + [ True + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 162 (remaining gas: 1039623.485 units remaining) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039623.440 units remaining) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 167 (remaining gas: 1039623.360 units remaining) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 168 (remaining gas: 1039623.280 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 171 (remaining gas: 1039623.125 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 170 (remaining gas: 1039623.080 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 169 (remaining gas: 1039623.080 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 172 (remaining gas: 1039602.730 units remaining) + [ 0x050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 173 (remaining gas: 1039564.400 units remaining) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @packed.unpacked + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 181 (remaining gas: 1039564.265 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @packed.unpacked.some + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 175 (remaining gas: 1039564.220 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @packed.unpacked.some + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 184 (remaining gas: 1039563.920 units remaining) + [ 0 + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 185 (remaining gas: 1039563.845 units remaining) + [ True + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039563.800 units remaining) + [ True + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 187 (remaining gas: 1039563.700 units remaining) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039563.655 units remaining) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 192 (remaining gas: 1039563.575 units remaining) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 193 (remaining gas: 1039563.495 units remaining) + [ "2019-09-09T08:35:33Z" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 196 (remaining gas: 1039563.340 units remaining) + [ "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 195 (remaining gas: 1039563.295 units remaining) + [ "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 194 (remaining gas: 1039563.295 units remaining) + [ "2019-09-09T08:35:33Z" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 197 (remaining gas: 1039555.025 units remaining) + [ 0x050095bbb0d70b @packed + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 198 (remaining gas: 1039547.755 units remaining) + [ (Some "2019-09-09T08:35:33Z") @packed.unpacked + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 206 (remaining gas: 1039547.620 units remaining) + [ "2019-09-09T08:35:33Z" @packed.unpacked.some + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 200 (remaining gas: 1039547.575 units remaining) + [ "2019-09-09T08:35:33Z" @packed.unpacked.some + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 209 (remaining gas: 1039547.345 units remaining) + [ 0 + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 210 (remaining gas: 1039547.270 units remaining) + [ True + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: -1 (remaining gas: 1039547.225 units remaining) + [ True + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 212 (remaining gas: 1039547.125 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: -1 (remaining gas: 1039547.080 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 217 (remaining gas: 1039547 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 218 (remaining gas: 1039516.130 units remaining) + [ 0x050a000000160000bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 219 (remaining gas: 1039419.860 units remaining) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @packed.unpacked + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 227 (remaining gas: 1039419.725 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @packed.unpacked.some + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 221 (remaining gas: 1039419.680 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @packed.unpacked.some + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 230 (remaining gas: 1039419.372 units remaining) + [ 0 ] + - location: 231 (remaining gas: 1039419.297 units remaining) + [ True ] + - location: -1 (remaining gas: 1039419.252 units remaining) + [ True ] + - location: 233 (remaining gas: 1039419.152 units remaining) + [ ] + - location: -1 (remaining gas: 1039419.107 units remaining) + [ ] + - location: 238 (remaining gas: 1039419.032 units remaining) + [ 0 ] + - location: 241 (remaining gas: 1039410.762 units remaining) + [ 0x050000 @packed ] + - location: 242 (remaining gas: 1039405.492 units remaining) + [ (Some 0) @packed.unpacked ] + - location: 250 (remaining gas: 1039405.357 units remaining) + [ 0 @packed.unpacked.some ] + - location: 244 (remaining gas: 1039405.312 units remaining) + [ 0 @packed.unpacked.some ] + - location: 251 (remaining gas: 1039405.237 units remaining) + [ ] + - location: 252 (remaining gas: 1039405.162 units remaining) + [ -1 ] + - location: 255 (remaining gas: 1039396.892 units remaining) + [ 0x050041 @packed ] + - location: 256 (remaining gas: 1039293.862 units remaining) + [ None @packed.unpacked ] + - location: 260 (remaining gas: 1039293.727 units remaining) + [ ] + - location: 258 (remaining gas: 1039293.682 units remaining) + [ ] + - location: 265 (remaining gas: 1039293.607 units remaining) + [ 0x ] + - location: 268 (remaining gas: 1039293.577 units remaining) + [ None @unpacked ] + - location: 272 (remaining gas: 1039293.442 units remaining) + [ ] + - location: 270 (remaining gas: 1039293.397 units remaining) + [ ] + - location: 277 (remaining gas: 1039293.322 units remaining) + [ 0x04 ] + - location: 280 (remaining gas: 1039293.292 units remaining) + [ None @unpacked ] + - location: 284 (remaining gas: 1039293.157 units remaining) + [ ] + - location: 282 (remaining gas: 1039293.112 units remaining) + [ ] + - location: 289 (remaining gas: 1039293.037 units remaining) + [ 0x05 ] + - location: 292 (remaining gas: 1039293.007 units remaining) + [ None @unpacked ] + - location: 296 (remaining gas: 1039292.872 units remaining) + [ ] + - location: 294 (remaining gas: 1039292.827 units remaining) + [ ] + - location: 301 (remaining gas: 1039292.752 units remaining) + [ Unit ] + - location: 302 (remaining gas: 1039292.677 units remaining) + [ {} + Unit ] + - location: 304 (remaining gas: 1039292.602 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039292.557 units remaining) + [ (Pair {} Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev.tz-Unit-(Pair -1 (Pair 1 (Pair \"foobar\".735d9ae802.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev.tz-Unit-(Pair -1 (Pair 1 (Pair \"foobar\".735d9ae802.out" new file mode 100644 index 0000000000000000000000000000000000000000..9b9154fe8c2557eb12863e9b467d4faae1e0c273 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev.tz-Unit-(Pair -1 (Pair 1 (Pair \"foobar\".735d9ae802.out" @@ -0,0 +1,900 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[packunpack_rev.tz-Unit-(Pair -1 (Pair 1 (Pair "foobar" (Pair 0x00AABBCC (Pair 1000 (Pair False (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"))))))))-Unit0] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039758.056 units remaining) + [ (Pair (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + Unit) ] + - location: 16 (remaining gas: 1039757.976 units remaining) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @parameter ] + - location: 17 (remaining gas: 1039757.896 units remaining) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @parameter + (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @parameter ] + - location: 18 (remaining gas: 1039757.816 units remaining) + [ -1 + (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @parameter ] + - location: 21 (remaining gas: 1039757.661 units remaining) + [ -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 20 (remaining gas: 1039757.616 units remaining) + [ -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 19 (remaining gas: 1039757.616 units remaining) + [ -1 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 22 (remaining gas: 1039749.346 units remaining) + [ 0x050041 @packed + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 23 (remaining gas: 1039742.076 units remaining) + [ (Some -1) @packed.unpacked + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 31 (remaining gas: 1039741.941 units remaining) + [ -1 @packed.unpacked.some + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 25 (remaining gas: 1039741.896 units remaining) + [ -1 @packed.unpacked.some + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 34 (remaining gas: 1039741.656 units remaining) + [ 0 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 35 (remaining gas: 1039741.581 units remaining) + [ True + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039741.536 units remaining) + [ True + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 37 (remaining gas: 1039741.436 units remaining) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039741.391 units remaining) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 42 (remaining gas: 1039741.311 units remaining) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 43 (remaining gas: 1039741.231 units remaining) + [ 1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 46 (remaining gas: 1039741.076 units remaining) + [ 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 45 (remaining gas: 1039741.031 units remaining) + [ 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 44 (remaining gas: 1039741.031 units remaining) + [ 1 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 47 (remaining gas: 1039732.761 units remaining) + [ 0x050001 @packed + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 48 (remaining gas: 1039725.491 units remaining) + [ (Some 1) @packed.unpacked + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 56 (remaining gas: 1039725.356 units remaining) + [ 1 @packed.unpacked.some + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 50 (remaining gas: 1039725.311 units remaining) + [ 1 @packed.unpacked.some + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 59 (remaining gas: 1039725.071 units remaining) + [ 0 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 60 (remaining gas: 1039724.996 units remaining) + [ True + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039724.951 units remaining) + [ True + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 62 (remaining gas: 1039724.851 units remaining) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039724.806 units remaining) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 67 (remaining gas: 1039724.726 units remaining) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 68 (remaining gas: 1039724.646 units remaining) + [ "foobar" + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 71 (remaining gas: 1039724.491 units remaining) + [ "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 70 (remaining gas: 1039724.446 units remaining) + [ "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 69 (remaining gas: 1039724.446 units remaining) + [ "foobar" + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 72 (remaining gas: 1039712.176 units remaining) + [ 0x050100000006666f6f626172 @packed + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 73 (remaining gas: 1039704.832 units remaining) + [ (Some "foobar") @packed.unpacked + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 81 (remaining gas: 1039704.697 units remaining) + [ "foobar" @packed.unpacked.some + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 75 (remaining gas: 1039704.652 units remaining) + [ "foobar" @packed.unpacked.some + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 84 (remaining gas: 1039704.442 units remaining) + [ 0 + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 85 (remaining gas: 1039704.367 units remaining) + [ True + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039704.322 units remaining) + [ True + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 87 (remaining gas: 1039704.222 units remaining) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039704.177 units remaining) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 92 (remaining gas: 1039704.097 units remaining) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 93 (remaining gas: 1039704.017 units remaining) + [ 0x00aabbcc + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 96 (remaining gas: 1039703.862 units remaining) + [ 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 95 (remaining gas: 1039703.817 units remaining) + [ 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 94 (remaining gas: 1039703.817 units remaining) + [ 0x00aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 97 (remaining gas: 1039691.547 units remaining) + [ 0x050a0000000400aabbcc @packed + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 98 (remaining gas: 1039657.277 units remaining) + [ (Some 0x00aabbcc) @packed.unpacked + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 106 (remaining gas: 1039657.142 units remaining) + [ 0x00aabbcc @packed.unpacked.some + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 100 (remaining gas: 1039657.097 units remaining) + [ 0x00aabbcc @packed.unpacked.some + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 109 (remaining gas: 1039656.887 units remaining) + [ 0 + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 110 (remaining gas: 1039656.812 units remaining) + [ True + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039656.767 units remaining) + [ True + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 112 (remaining gas: 1039656.667 units remaining) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039656.622 units remaining) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 117 (remaining gas: 1039656.542 units remaining) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 118 (remaining gas: 1039656.462 units remaining) + [ 1000 + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 121 (remaining gas: 1039656.307 units remaining) + [ 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 120 (remaining gas: 1039656.262 units remaining) + [ 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 119 (remaining gas: 1039656.262 units remaining) + [ 1000 + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 122 (remaining gas: 1039647.992 units remaining) + [ 0x0500a80f @packed + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 123 (remaining gas: 1039640.722 units remaining) + [ (Some 1000) @packed.unpacked + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 131 (remaining gas: 1039640.587 units remaining) + [ 1000 @packed.unpacked.some + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 125 (remaining gas: 1039640.542 units remaining) + [ 1000 @packed.unpacked.some + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 134 (remaining gas: 1039640.348 units remaining) + [ 0 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 135 (remaining gas: 1039640.273 units remaining) + [ True + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039640.228 units remaining) + [ True + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 137 (remaining gas: 1039640.128 units remaining) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039640.083 units remaining) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 142 (remaining gas: 1039640.003 units remaining) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 143 (remaining gas: 1039639.923 units remaining) + [ False + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 146 (remaining gas: 1039639.768 units remaining) + [ False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 145 (remaining gas: 1039639.723 units remaining) + [ False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 144 (remaining gas: 1039639.723 units remaining) + [ False + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 147 (remaining gas: 1039631.453 units remaining) + [ 0x050303 @packed + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 148 (remaining gas: 1039624.183 units remaining) + [ (Some False) @packed.unpacked + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 156 (remaining gas: 1039624.048 units remaining) + [ False @packed.unpacked.some + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 150 (remaining gas: 1039624.003 units remaining) + [ False @packed.unpacked.some + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 159 (remaining gas: 1039623.705 units remaining) + [ 0 + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 160 (remaining gas: 1039623.630 units remaining) + [ True + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039623.585 units remaining) + [ True + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 162 (remaining gas: 1039623.485 units remaining) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039623.440 units remaining) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 167 (remaining gas: 1039623.360 units remaining) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 168 (remaining gas: 1039623.280 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 171 (remaining gas: 1039623.125 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 170 (remaining gas: 1039623.080 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 169 (remaining gas: 1039623.080 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 172 (remaining gas: 1039602.730 units remaining) + [ 0x050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 173 (remaining gas: 1039564.400 units remaining) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @packed.unpacked + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 181 (remaining gas: 1039564.265 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @packed.unpacked.some + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 175 (remaining gas: 1039564.220 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @packed.unpacked.some + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 184 (remaining gas: 1039563.920 units remaining) + [ 0 + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 185 (remaining gas: 1039563.845 units remaining) + [ True + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039563.800 units remaining) + [ True + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 187 (remaining gas: 1039563.700 units remaining) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: -1 (remaining gas: 1039563.655 units remaining) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 192 (remaining gas: 1039563.575 units remaining) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 193 (remaining gas: 1039563.495 units remaining) + [ "2019-09-09T08:35:33Z" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 196 (remaining gas: 1039563.340 units remaining) + [ "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 195 (remaining gas: 1039563.295 units remaining) + [ "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 194 (remaining gas: 1039563.295 units remaining) + [ "2019-09-09T08:35:33Z" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 197 (remaining gas: 1039555.025 units remaining) + [ 0x050095bbb0d70b @packed + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 198 (remaining gas: 1039547.755 units remaining) + [ (Some "2019-09-09T08:35:33Z") @packed.unpacked + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 206 (remaining gas: 1039547.620 units remaining) + [ "2019-09-09T08:35:33Z" @packed.unpacked.some + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 200 (remaining gas: 1039547.575 units remaining) + [ "2019-09-09T08:35:33Z" @packed.unpacked.some + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 209 (remaining gas: 1039547.345 units remaining) + [ 0 + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 210 (remaining gas: 1039547.270 units remaining) + [ True + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: -1 (remaining gas: 1039547.225 units remaining) + [ True + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 212 (remaining gas: 1039547.125 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: -1 (remaining gas: 1039547.080 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 217 (remaining gas: 1039547 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 218 (remaining gas: 1039516.130 units remaining) + [ 0x050a000000160000bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 219 (remaining gas: 1039419.860 units remaining) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @packed.unpacked + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 227 (remaining gas: 1039419.725 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @packed.unpacked.some + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 221 (remaining gas: 1039419.680 units remaining) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" @packed.unpacked.some + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 230 (remaining gas: 1039419.372 units remaining) + [ 0 ] + - location: 231 (remaining gas: 1039419.297 units remaining) + [ True ] + - location: -1 (remaining gas: 1039419.252 units remaining) + [ True ] + - location: 233 (remaining gas: 1039419.152 units remaining) + [ ] + - location: -1 (remaining gas: 1039419.107 units remaining) + [ ] + - location: 238 (remaining gas: 1039419.032 units remaining) + [ 0 ] + - location: 241 (remaining gas: 1039410.762 units remaining) + [ 0x050000 @packed ] + - location: 242 (remaining gas: 1039405.492 units remaining) + [ (Some 0) @packed.unpacked ] + - location: 250 (remaining gas: 1039405.357 units remaining) + [ 0 @packed.unpacked.some ] + - location: 244 (remaining gas: 1039405.312 units remaining) + [ 0 @packed.unpacked.some ] + - location: 251 (remaining gas: 1039405.237 units remaining) + [ ] + - location: 252 (remaining gas: 1039405.162 units remaining) + [ -1 ] + - location: 255 (remaining gas: 1039396.892 units remaining) + [ 0x050041 @packed ] + - location: 256 (remaining gas: 1039293.862 units remaining) + [ None @packed.unpacked ] + - location: 260 (remaining gas: 1039293.727 units remaining) + [ ] + - location: 258 (remaining gas: 1039293.682 units remaining) + [ ] + - location: 265 (remaining gas: 1039293.607 units remaining) + [ 0x ] + - location: 268 (remaining gas: 1039293.577 units remaining) + [ None @unpacked ] + - location: 272 (remaining gas: 1039293.442 units remaining) + [ ] + - location: 270 (remaining gas: 1039293.397 units remaining) + [ ] + - location: 277 (remaining gas: 1039293.322 units remaining) + [ 0x04 ] + - location: 280 (remaining gas: 1039293.292 units remaining) + [ None @unpacked ] + - location: 284 (remaining gas: 1039293.157 units remaining) + [ ] + - location: 282 (remaining gas: 1039293.112 units remaining) + [ ] + - location: 289 (remaining gas: 1039293.037 units remaining) + [ 0x05 ] + - location: 292 (remaining gas: 1039293.007 units remaining) + [ None @unpacked ] + - location: 296 (remaining gas: 1039292.872 units remaining) + [ ] + - location: 294 (remaining gas: 1039292.827 units remaining) + [ ] + - location: 301 (remaining gas: 1039292.752 units remaining) + [ Unit ] + - location: 302 (remaining gas: 1039292.677 units remaining) + [ {} + Unit ] + - location: 304 (remaining gas: 1039292.602 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039292.557 units remaining) + [ (Pair {} Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev_cty.tz-Unit-(Pair \"edpkuBknW28nW72KG6RoH.1ac5de50fb.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev_cty.tz-Unit-(Pair \"edpkuBknW28nW72KG6RoH.1ac5de50fb.out" new file mode 100644 index 0000000000000000000000000000000000000000..642b22b3c83760b82504df43b47468fade3915c7 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev_cty.tz-Unit-(Pair \"edpkuBknW28nW72KG6RoH.1ac5de50fb.out" @@ -0,0 +1,1260 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[packunpack_rev_cty.tz-Unit-(Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" (Pair Unit (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") (Pair { Unit } (Pair { True } (Pair (Pair 19 10) (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK } )))))))))-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 27 (remaining gas: 1039743.141 units remaining) + [ (Pair (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + Unit) ] + - location: 28 (remaining gas: 1039743.061 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) @parameter ] + - location: 29 (remaining gas: 1039742.981 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) @parameter + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) @parameter ] + - location: 30 (remaining gas: 1039742.901 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) @parameter ] + - location: 33 (remaining gas: 1039742.746 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 32 (remaining gas: 1039742.701 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 31 (remaining gas: 1039742.701 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 34 (remaining gas: 1039717.941 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 37 (remaining gas: 1039693.106 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 38 (remaining gas: 1039625.836 units remaining) + [ (Some "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav") @packed.unpacked + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 46 (remaining gas: 1039625.701 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" @packed.unpacked.some + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 40 (remaining gas: 1039625.656 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" @packed.unpacked.some + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 47 (remaining gas: 1039600.896 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed.unpacked.some.packed + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039600.851 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed.unpacked.some.packed + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 35 (remaining gas: 1039600.851 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed + 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed.unpacked.some.packed + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 50 (remaining gas: 1039600.640 units remaining) + [ 0 + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 51 (remaining gas: 1039600.565 units remaining) + [ True + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039600.520 units remaining) + [ True + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 53 (remaining gas: 1039600.420 units remaining) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039600.375 units remaining) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 58 (remaining gas: 1039600.295 units remaining) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 59 (remaining gas: 1039600.215 units remaining) + [ Unit + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 62 (remaining gas: 1039600.060 units remaining) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 61 (remaining gas: 1039600.015 units remaining) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 60 (remaining gas: 1039600.015 units remaining) + [ Unit + Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 63 (remaining gas: 1039591.745 units remaining) + [ 0x05030b @packed + Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 66 (remaining gas: 1039583.400 units remaining) + [ 0x05030b @packed + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 67 (remaining gas: 1039576.130 units remaining) + [ (Some Unit) @packed.unpacked + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 75 (remaining gas: 1039575.995 units remaining) + [ Unit @packed.unpacked.some + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 69 (remaining gas: 1039575.950 units remaining) + [ Unit @packed.unpacked.some + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 76 (remaining gas: 1039567.680 units remaining) + [ 0x05030b @packed.unpacked.some.packed + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039567.635 units remaining) + [ 0x05030b @packed.unpacked.some.packed + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 64 (remaining gas: 1039567.635 units remaining) + [ 0x05030b @packed + 0x05030b @packed.unpacked.some.packed + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 79 (remaining gas: 1039567.425 units remaining) + [ 0 + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 80 (remaining gas: 1039567.350 units remaining) + [ True + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039567.305 units remaining) + [ True + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 82 (remaining gas: 1039567.205 units remaining) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039567.160 units remaining) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 87 (remaining gas: 1039567.080 units remaining) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 88 (remaining gas: 1039567 units remaining) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 91 (remaining gas: 1039566.845 units remaining) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 90 (remaining gas: 1039566.800 units remaining) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 89 (remaining gas: 1039566.800 units remaining) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 92 (remaining gas: 1039526.490 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 95 (remaining gas: 1039486.105 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 96 (remaining gas: 1039437.805 units remaining) + [ (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe") @packed.unpacked + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 104 (remaining gas: 1039437.670 units remaining) + [ "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe" @packed.unpacked.some + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 98 (remaining gas: 1039437.625 units remaining) + [ "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe" @packed.unpacked.some + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 105 (remaining gas: 1039397.315 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed.unpacked.some.packed + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039397.270 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed.unpacked.some.packed + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 93 (remaining gas: 1039397.270 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed + 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed.unpacked.some.packed + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 108 (remaining gas: 1039397.058 units remaining) + [ 0 + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 109 (remaining gas: 1039396.983 units remaining) + [ True + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039396.938 units remaining) + [ True + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 111 (remaining gas: 1039396.838 units remaining) + [ (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039396.793 units remaining) + [ (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 116 (remaining gas: 1039396.713 units remaining) + [ (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 117 (remaining gas: 1039396.633 units remaining) + [ (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 120 (remaining gas: 1039396.478 units remaining) + [ (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 119 (remaining gas: 1039396.433 units remaining) + [ (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 118 (remaining gas: 1039396.433 units remaining) + [ (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 121 (remaining gas: 1039355.883 units remaining) + [ 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 124 (remaining gas: 1039315.258 units remaining) + [ 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 125 (remaining gas: 1039252.718 units remaining) + [ (Some (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe")) @packed.unpacked + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 134 (remaining gas: 1039252.583 units remaining) + [ (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe") @packed.unpacked.some + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 128 (remaining gas: 1039252.538 units remaining) + [ (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe") @packed.unpacked.some + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 135 (remaining gas: 1039211.988 units remaining) + [ 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed.unpacked.some.packed + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039211.943 units remaining) + [ 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed.unpacked.some.packed + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 122 (remaining gas: 1039211.943 units remaining) + [ 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed + 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed.unpacked.some.packed + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 138 (remaining gas: 1039211.731 units remaining) + [ 0 + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 139 (remaining gas: 1039211.656 units remaining) + [ True + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039211.611 units remaining) + [ True + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 141 (remaining gas: 1039211.511 units remaining) + [ (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039211.466 units remaining) + [ (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 146 (remaining gas: 1039211.386 units remaining) + [ (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 147 (remaining gas: 1039211.306 units remaining) + [ { Unit } + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 150 (remaining gas: 1039211.151 units remaining) + [ { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 149 (remaining gas: 1039211.106 units remaining) + [ { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 148 (remaining gas: 1039211.106 units remaining) + [ { Unit } + { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 151 (remaining gas: 1039202.596 units remaining) + [ 0x050200000002030b @packed + { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 154 (remaining gas: 1039194.011 units remaining) + [ 0x050200000002030b @packed + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 155 (remaining gas: 1039172.501 units remaining) + [ (Some { Unit }) @packed.unpacked + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 164 (remaining gas: 1039172.366 units remaining) + [ { Unit } @packed.unpacked.some + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 158 (remaining gas: 1039172.321 units remaining) + [ { Unit } @packed.unpacked.some + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 165 (remaining gas: 1039163.811 units remaining) + [ 0x050200000002030b @packed.unpacked.some.packed + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039163.766 units remaining) + [ 0x050200000002030b @packed.unpacked.some.packed + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 152 (remaining gas: 1039163.766 units remaining) + [ 0x050200000002030b @packed + 0x050200000002030b @packed.unpacked.some.packed + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 168 (remaining gas: 1039163.556 units remaining) + [ 0 + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 169 (remaining gas: 1039163.481 units remaining) + [ True + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039163.436 units remaining) + [ True + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 171 (remaining gas: 1039163.336 units remaining) + [ (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039163.291 units remaining) + [ (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 176 (remaining gas: 1039163.211 units remaining) + [ (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 177 (remaining gas: 1039163.131 units remaining) + [ { True } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 180 (remaining gas: 1039162.976 units remaining) + [ { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 179 (remaining gas: 1039162.931 units remaining) + [ { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 178 (remaining gas: 1039162.931 units remaining) + [ { True } + { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 181 (remaining gas: 1039154.421 units remaining) + [ 0x050200000002030a @packed + { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 184 (remaining gas: 1039145.836 units remaining) + [ 0x050200000002030a @packed + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 185 (remaining gas: 1039124.245 units remaining) + [ (Some { True }) @packed.unpacked + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 194 (remaining gas: 1039124.110 units remaining) + [ { True } @packed.unpacked.some + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 188 (remaining gas: 1039124.065 units remaining) + [ { True } @packed.unpacked.some + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 195 (remaining gas: 1039115.555 units remaining) + [ 0x050200000002030a @packed.unpacked.some.packed + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039115.510 units remaining) + [ 0x050200000002030a @packed.unpacked.some.packed + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 182 (remaining gas: 1039115.510 units remaining) + [ 0x050200000002030a @packed + 0x050200000002030a @packed.unpacked.some.packed + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 198 (remaining gas: 1039115.300 units remaining) + [ 0 + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 199 (remaining gas: 1039115.225 units remaining) + [ True + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039115.180 units remaining) + [ True + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 201 (remaining gas: 1039115.080 units remaining) + [ (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039115.035 units remaining) + [ (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 206 (remaining gas: 1039114.955 units remaining) + [ (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 207 (remaining gas: 1039114.875 units remaining) + [ (Pair 19 10) + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 210 (remaining gas: 1039114.720 units remaining) + [ (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 209 (remaining gas: 1039114.675 units remaining) + [ (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 208 (remaining gas: 1039114.675 units remaining) + [ (Pair 19 10) + (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 211 (remaining gas: 1039105.925 units remaining) + [ 0x0507070013000a @packed + (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 214 (remaining gas: 1039097.100 units remaining) + [ 0x0507070013000a @packed + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 215 (remaining gas: 1039061.350 units remaining) + [ (Some (Pair 19 10)) @packed.unpacked + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 225 (remaining gas: 1039061.215 units remaining) + [ (Pair 19 10) @packed.unpacked.some + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 219 (remaining gas: 1039061.170 units remaining) + [ (Pair 19 10) @packed.unpacked.some + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 226 (remaining gas: 1039052.420 units remaining) + [ 0x0507070013000a @packed.unpacked.some.packed + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039052.375 units remaining) + [ 0x0507070013000a @packed.unpacked.some.packed + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 212 (remaining gas: 1039052.375 units remaining) + [ 0x0507070013000a @packed + 0x0507070013000a @packed.unpacked.some.packed + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 229 (remaining gas: 1039052.165 units remaining) + [ 0 + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 230 (remaining gas: 1039052.090 units remaining) + [ True + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039052.045 units remaining) + [ True + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 232 (remaining gas: 1039051.945 units remaining) + [ (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: -1 (remaining gas: 1039051.900 units remaining) + [ (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 237 (remaining gas: 1039051.820 units remaining) + [ (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 238 (remaining gas: 1039051.740 units remaining) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 241 (remaining gas: 1039051.585 units remaining) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 240 (remaining gas: 1039051.540 units remaining) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 239 (remaining gas: 1039051.540 units remaining) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 242 (remaining gas: 1039030.950 units remaining) + [ 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 245 (remaining gas: 1039010.285 units remaining) + [ 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 246 (remaining gas: 1038957.715 units remaining) + [ (Some (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5")) @packed.unpacked + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 256 (remaining gas: 1038957.580 units remaining) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @packed.unpacked.some + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 250 (remaining gas: 1038957.535 units remaining) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") @packed.unpacked.some + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 257 (remaining gas: 1038936.945 units remaining) + [ 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed.unpacked.some.packed + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: -1 (remaining gas: 1038936.900 units remaining) + [ 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed.unpacked.some.packed + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 243 (remaining gas: 1038936.900 units remaining) + [ 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed + 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a @packed.unpacked.some.packed + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 260 (remaining gas: 1038936.690 units remaining) + [ 0 + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 261 (remaining gas: 1038936.615 units remaining) + [ True + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: -1 (remaining gas: 1038936.570 units remaining) + [ True + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 263 (remaining gas: 1038936.470 units remaining) + [ (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: -1 (remaining gas: 1038936.425 units remaining) + [ (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 268 (remaining gas: 1038936.345 units remaining) + [ (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 269 (remaining gas: 1038936.265 units remaining) + [ { Elt 0 "foo" ; Elt 1 "bar" } + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 272 (remaining gas: 1038936.110 units remaining) + [ { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 271 (remaining gas: 1038936.065 units remaining) + [ { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 270 (remaining gas: 1038936.065 units remaining) + [ { Elt 0 "foo" ; Elt 1 "bar" } + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 273 (remaining gas: 1038914.635 units remaining) + [ 0x050200000018070400000100000003666f6f070400010100000003626172 @packed + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 276 (remaining gas: 1038893.130 units remaining) + [ 0x050200000018070400000100000003666f6f070400010100000003626172 @packed + { PACK } ] + - location: 277 (remaining gas: 1038802.502 units remaining) + [ (Some { Elt 0 "foo" ; Elt 1 "bar" }) @packed.unpacked + { PACK } ] + - location: 287 (remaining gas: 1038802.367 units remaining) + [ { Elt 0 "foo" ; Elt 1 "bar" } @packed.unpacked.some + { PACK } ] + - location: 281 (remaining gas: 1038802.322 units remaining) + [ { Elt 0 "foo" ; Elt 1 "bar" } @packed.unpacked.some + { PACK } ] + - location: 288 (remaining gas: 1038780.892 units remaining) + [ 0x050200000018070400000100000003666f6f070400010100000003626172 @packed.unpacked.some.packed + { PACK } ] + - location: -1 (remaining gas: 1038780.847 units remaining) + [ 0x050200000018070400000100000003666f6f070400010100000003626172 @packed.unpacked.some.packed + { PACK } ] + - location: 274 (remaining gas: 1038780.847 units remaining) + [ 0x050200000018070400000100000003666f6f070400010100000003626172 @packed + 0x050200000018070400000100000003666f6f070400010100000003626172 @packed.unpacked.some.packed + { PACK } ] + - location: 291 (remaining gas: 1038780.637 units remaining) + [ 0 + { PACK } ] + - location: 292 (remaining gas: 1038780.562 units remaining) + [ True + { PACK } ] + - location: -1 (remaining gas: 1038780.517 units remaining) + [ True + { PACK } ] + - location: 294 (remaining gas: 1038780.417 units remaining) + [ { PACK } ] + - location: -1 (remaining gas: 1038780.372 units remaining) + [ { PACK } ] + - location: 299 (remaining gas: 1038780.292 units remaining) + [ { PACK } + { PACK } ] + - location: 300 (remaining gas: 1038771.522 units remaining) + [ 0x050200000002030c @packed + { PACK } ] + - location: 303 (remaining gas: 1038762.677 units remaining) + [ 0x050200000002030c @packed ] + - location: 304 (remaining gas: 1038740.527 units remaining) + [ (Some { PACK }) @packed.unpacked ] + - location: 314 (remaining gas: 1038740.392 units remaining) + [ { PACK } @packed.unpacked.some ] + - location: 308 (remaining gas: 1038740.347 units remaining) + [ { PACK } @packed.unpacked.some ] + - location: 315 (remaining gas: 1038731.577 units remaining) + [ 0x050200000002030c @packed.unpacked.some.packed ] + - location: -1 (remaining gas: 1038731.532 units remaining) + [ 0x050200000002030c @packed.unpacked.some.packed ] + - location: 301 (remaining gas: 1038731.532 units remaining) + [ 0x050200000002030c @packed + 0x050200000002030c @packed.unpacked.some.packed ] + - location: 318 (remaining gas: 1038731.322 units remaining) + [ 0 ] + - location: 319 (remaining gas: 1038731.247 units remaining) + [ True ] + - location: -1 (remaining gas: 1038731.202 units remaining) + [ True ] + - location: 321 (remaining gas: 1038731.102 units remaining) + [ ] + - location: -1 (remaining gas: 1038731.057 units remaining) + [ ] + - location: 326 (remaining gas: 1038730.982 units remaining) + [ Unit ] + - location: 327 (remaining gas: 1038730.907 units remaining) + [ {} + Unit ] + - location: 329 (remaining gas: 1038730.832 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1038730.787 units remaining) + [ (Pair {} Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev_cty.tz-Unit-(Pair \"edpkuBknW28nW72KG6RoH.4e20b52378.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev_cty.tz-Unit-(Pair \"edpkuBknW28nW72KG6RoH.4e20b52378.out" new file mode 100644 index 0000000000000000000000000000000000000000..2aae249f05264fa3301efb19714d844d81b2c2d0 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[packunpack_rev_cty.tz-Unit-(Pair \"edpkuBknW28nW72KG6RoH.4e20b52378.out" @@ -0,0 +1,1089 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[packunpack_rev_cty.tz-Unit-(Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" (Pair Unit (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" (Pair None (Pair { } (Pair { } (Pair (Pair 40 -10) (Pair (Right "2019-09-09T08:35:33Z") (Pair { } { DUP ; DROP ; PACK } )))))))))-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 27 (remaining gas: 1039753.330 units remaining) + [ (Pair (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + Unit) ] + - location: 28 (remaining gas: 1039753.250 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) @parameter ] + - location: 29 (remaining gas: 1039753.170 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) @parameter + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) @parameter ] + - location: 30 (remaining gas: 1039753.090 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) @parameter ] + - location: 33 (remaining gas: 1039752.935 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 32 (remaining gas: 1039752.890 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 31 (remaining gas: 1039752.890 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 34 (remaining gas: 1039728.130 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 37 (remaining gas: 1039703.295 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 38 (remaining gas: 1039636.025 units remaining) + [ (Some "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav") @packed.unpacked + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 46 (remaining gas: 1039635.890 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" @packed.unpacked.some + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 40 (remaining gas: 1039635.845 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" @packed.unpacked.some + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 47 (remaining gas: 1039611.085 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed.unpacked.some.packed + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039611.040 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed.unpacked.some.packed + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 35 (remaining gas: 1039611.040 units remaining) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed + 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f @packed.unpacked.some.packed + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 50 (remaining gas: 1039610.829 units remaining) + [ 0 + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 51 (remaining gas: 1039610.754 units remaining) + [ True + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039610.709 units remaining) + [ True + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 53 (remaining gas: 1039610.609 units remaining) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039610.564 units remaining) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 58 (remaining gas: 1039610.484 units remaining) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 59 (remaining gas: 1039610.404 units remaining) + [ Unit + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 62 (remaining gas: 1039610.249 units remaining) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 61 (remaining gas: 1039610.204 units remaining) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 60 (remaining gas: 1039610.204 units remaining) + [ Unit + Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 63 (remaining gas: 1039601.934 units remaining) + [ 0x05030b @packed + Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 66 (remaining gas: 1039593.589 units remaining) + [ 0x05030b @packed + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 67 (remaining gas: 1039586.319 units remaining) + [ (Some Unit) @packed.unpacked + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 75 (remaining gas: 1039586.184 units remaining) + [ Unit @packed.unpacked.some + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 69 (remaining gas: 1039586.139 units remaining) + [ Unit @packed.unpacked.some + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 76 (remaining gas: 1039577.869 units remaining) + [ 0x05030b @packed.unpacked.some.packed + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039577.824 units remaining) + [ 0x05030b @packed.unpacked.some.packed + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 64 (remaining gas: 1039577.824 units remaining) + [ 0x05030b @packed + 0x05030b @packed.unpacked.some.packed + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 79 (remaining gas: 1039577.614 units remaining) + [ 0 + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 80 (remaining gas: 1039577.539 units remaining) + [ True + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039577.494 units remaining) + [ True + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 82 (remaining gas: 1039577.394 units remaining) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039577.349 units remaining) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 87 (remaining gas: 1039577.269 units remaining) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 88 (remaining gas: 1039577.189 units remaining) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 91 (remaining gas: 1039577.034 units remaining) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 90 (remaining gas: 1039576.989 units remaining) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 89 (remaining gas: 1039576.989 units remaining) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 92 (remaining gas: 1039536.679 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 95 (remaining gas: 1039496.294 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 96 (remaining gas: 1039447.994 units remaining) + [ (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe") @packed.unpacked + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 104 (remaining gas: 1039447.859 units remaining) + [ "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe" @packed.unpacked.some + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 98 (remaining gas: 1039447.814 units remaining) + [ "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe" @packed.unpacked.some + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 105 (remaining gas: 1039407.504 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed.unpacked.some.packed + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039407.459 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed.unpacked.some.packed + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 93 (remaining gas: 1039407.459 units remaining) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed + 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 @packed.unpacked.some.packed + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 108 (remaining gas: 1039407.247 units remaining) + [ 0 + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 109 (remaining gas: 1039407.172 units remaining) + [ True + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039407.127 units remaining) + [ True + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 111 (remaining gas: 1039407.027 units remaining) + [ (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039406.982 units remaining) + [ (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 116 (remaining gas: 1039406.902 units remaining) + [ (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 117 (remaining gas: 1039406.822 units remaining) + [ None + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 120 (remaining gas: 1039406.667 units remaining) + [ None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 119 (remaining gas: 1039406.622 units remaining) + [ None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 118 (remaining gas: 1039406.622 units remaining) + [ None + None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 121 (remaining gas: 1039398.352 units remaining) + [ 0x050306 @packed + None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 124 (remaining gas: 1039390.007 units remaining) + [ 0x050306 @packed + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 125 (remaining gas: 1039382.737 units remaining) + [ (Some None) @packed.unpacked + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 134 (remaining gas: 1039382.602 units remaining) + [ None @packed.unpacked.some + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 128 (remaining gas: 1039382.557 units remaining) + [ None @packed.unpacked.some + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 135 (remaining gas: 1039374.287 units remaining) + [ 0x050306 @packed.unpacked.some.packed + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039374.242 units remaining) + [ 0x050306 @packed.unpacked.some.packed + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 122 (remaining gas: 1039374.242 units remaining) + [ 0x050306 @packed + 0x050306 @packed.unpacked.some.packed + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 138 (remaining gas: 1039374.032 units remaining) + [ 0 + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 139 (remaining gas: 1039373.957 units remaining) + [ True + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039373.912 units remaining) + [ True + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 141 (remaining gas: 1039373.812 units remaining) + [ (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039373.767 units remaining) + [ (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 146 (remaining gas: 1039373.687 units remaining) + [ (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 147 (remaining gas: 1039373.607 units remaining) + [ {} + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 150 (remaining gas: 1039373.452 units remaining) + [ {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 149 (remaining gas: 1039373.407 units remaining) + [ {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 148 (remaining gas: 1039373.407 units remaining) + [ {} + {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 151 (remaining gas: 1039365.137 units remaining) + [ 0x050200000000 @packed + {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 154 (remaining gas: 1039356.792 units remaining) + [ 0x050200000000 @packed + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 155 (remaining gas: 1039349.522 units remaining) + [ (Some {}) @packed.unpacked + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 164 (remaining gas: 1039349.387 units remaining) + [ {} @packed.unpacked.some + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 158 (remaining gas: 1039349.342 units remaining) + [ {} @packed.unpacked.some + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 165 (remaining gas: 1039341.072 units remaining) + [ 0x050200000000 @packed.unpacked.some.packed + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039341.027 units remaining) + [ 0x050200000000 @packed.unpacked.some.packed + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 152 (remaining gas: 1039341.027 units remaining) + [ 0x050200000000 @packed + 0x050200000000 @packed.unpacked.some.packed + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 168 (remaining gas: 1039340.817 units remaining) + [ 0 + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 169 (remaining gas: 1039340.742 units remaining) + [ True + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039340.697 units remaining) + [ True + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 171 (remaining gas: 1039340.597 units remaining) + [ (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039340.552 units remaining) + [ (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 176 (remaining gas: 1039340.472 units remaining) + [ (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 177 (remaining gas: 1039340.392 units remaining) + [ {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 180 (remaining gas: 1039340.237 units remaining) + [ {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 179 (remaining gas: 1039340.192 units remaining) + [ {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 178 (remaining gas: 1039340.192 units remaining) + [ {} + {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 181 (remaining gas: 1039331.922 units remaining) + [ 0x050200000000 @packed + {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 184 (remaining gas: 1039323.577 units remaining) + [ 0x050200000000 @packed + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 185 (remaining gas: 1039316.307 units remaining) + [ (Some {}) @packed.unpacked + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 194 (remaining gas: 1039316.172 units remaining) + [ {} @packed.unpacked.some + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 188 (remaining gas: 1039316.127 units remaining) + [ {} @packed.unpacked.some + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 195 (remaining gas: 1039307.857 units remaining) + [ 0x050200000000 @packed.unpacked.some.packed + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039307.812 units remaining) + [ 0x050200000000 @packed.unpacked.some.packed + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 182 (remaining gas: 1039307.812 units remaining) + [ 0x050200000000 @packed + 0x050200000000 @packed.unpacked.some.packed + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 198 (remaining gas: 1039307.602 units remaining) + [ 0 + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 199 (remaining gas: 1039307.527 units remaining) + [ True + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039307.482 units remaining) + [ True + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 201 (remaining gas: 1039307.382 units remaining) + [ (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039307.337 units remaining) + [ (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 206 (remaining gas: 1039307.257 units remaining) + [ (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 207 (remaining gas: 1039307.177 units remaining) + [ (Pair 40 -10) + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 210 (remaining gas: 1039307.022 units remaining) + [ (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 209 (remaining gas: 1039306.977 units remaining) + [ (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 208 (remaining gas: 1039306.977 units remaining) + [ (Pair 40 -10) + (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 211 (remaining gas: 1039298.227 units remaining) + [ 0x0507070028004a @packed + (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 214 (remaining gas: 1039289.402 units remaining) + [ 0x0507070028004a @packed + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 215 (remaining gas: 1039253.652 units remaining) + [ (Some (Pair 40 -10)) @packed.unpacked + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 225 (remaining gas: 1039253.517 units remaining) + [ (Pair 40 -10) @packed.unpacked.some + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 219 (remaining gas: 1039253.472 units remaining) + [ (Pair 40 -10) @packed.unpacked.some + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 226 (remaining gas: 1039244.722 units remaining) + [ 0x0507070028004a @packed.unpacked.some.packed + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039244.677 units remaining) + [ 0x0507070028004a @packed.unpacked.some.packed + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 212 (remaining gas: 1039244.677 units remaining) + [ 0x0507070028004a @packed + 0x0507070028004a @packed.unpacked.some.packed + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 229 (remaining gas: 1039244.467 units remaining) + [ 0 + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 230 (remaining gas: 1039244.392 units remaining) + [ True + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039244.347 units remaining) + [ True + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 232 (remaining gas: 1039244.247 units remaining) + [ (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039244.202 units remaining) + [ (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 237 (remaining gas: 1039244.122 units remaining) + [ (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 238 (remaining gas: 1039244.042 units remaining) + [ (Right "2019-09-09T08:35:33Z") + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 241 (remaining gas: 1039243.887 units remaining) + [ (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 240 (remaining gas: 1039243.842 units remaining) + [ (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 239 (remaining gas: 1039243.842 units remaining) + [ (Right "2019-09-09T08:35:33Z") + (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 242 (remaining gas: 1039233.332 units remaining) + [ 0x0505080095bbb0d70b @packed + (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 245 (remaining gas: 1039222.747 units remaining) + [ 0x0505080095bbb0d70b @packed + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 246 (remaining gas: 1039201.237 units remaining) + [ (Some (Right "2019-09-09T08:35:33Z")) @packed.unpacked + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 256 (remaining gas: 1039201.102 units remaining) + [ (Right "2019-09-09T08:35:33Z") @packed.unpacked.some + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 250 (remaining gas: 1039201.057 units remaining) + [ (Right "2019-09-09T08:35:33Z") @packed.unpacked.some + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 257 (remaining gas: 1039190.547 units remaining) + [ 0x0505080095bbb0d70b @packed.unpacked.some.packed + (Pair {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039190.502 units remaining) + [ 0x0505080095bbb0d70b @packed.unpacked.some.packed + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 243 (remaining gas: 1039190.502 units remaining) + [ 0x0505080095bbb0d70b @packed + 0x0505080095bbb0d70b @packed.unpacked.some.packed + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 260 (remaining gas: 1039190.292 units remaining) + [ 0 + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 261 (remaining gas: 1039190.217 units remaining) + [ True + (Pair {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039190.172 units remaining) + [ True + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 263 (remaining gas: 1039190.072 units remaining) + [ (Pair {} { DUP ; DROP ; PACK }) ] + - location: -1 (remaining gas: 1039190.027 units remaining) + [ (Pair {} { DUP ; DROP ; PACK }) ] + - location: 268 (remaining gas: 1039189.947 units remaining) + [ (Pair {} { DUP ; DROP ; PACK }) + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 269 (remaining gas: 1039189.867 units remaining) + [ {} + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 272 (remaining gas: 1039189.712 units remaining) + [ {} + { DUP ; DROP ; PACK } ] + - location: 271 (remaining gas: 1039189.667 units remaining) + [ {} + { DUP ; DROP ; PACK } ] + - location: 270 (remaining gas: 1039189.667 units remaining) + [ {} + {} + { DUP ; DROP ; PACK } ] + - location: 273 (remaining gas: 1039181.397 units remaining) + [ 0x050200000000 @packed + {} + { DUP ; DROP ; PACK } ] + - location: 276 (remaining gas: 1039173.052 units remaining) + [ 0x050200000000 @packed + { DUP ; DROP ; PACK } ] + - location: 277 (remaining gas: 1039165.782 units remaining) + [ (Some {}) @packed.unpacked + { DUP ; DROP ; PACK } ] + - location: 287 (remaining gas: 1039165.647 units remaining) + [ {} @packed.unpacked.some + { DUP ; DROP ; PACK } ] + - location: 281 (remaining gas: 1039165.602 units remaining) + [ {} @packed.unpacked.some + { DUP ; DROP ; PACK } ] + - location: 288 (remaining gas: 1039157.332 units remaining) + [ 0x050200000000 @packed.unpacked.some.packed + { DUP ; DROP ; PACK } ] + - location: -1 (remaining gas: 1039157.287 units remaining) + [ 0x050200000000 @packed.unpacked.some.packed + { DUP ; DROP ; PACK } ] + - location: 274 (remaining gas: 1039157.287 units remaining) + [ 0x050200000000 @packed + 0x050200000000 @packed.unpacked.some.packed + { DUP ; DROP ; PACK } ] + - location: 291 (remaining gas: 1039157.077 units remaining) + [ 0 + { DUP ; DROP ; PACK } ] + - location: 292 (remaining gas: 1039157.002 units remaining) + [ True + { DUP ; DROP ; PACK } ] + - location: -1 (remaining gas: 1039156.957 units remaining) + [ True + { DUP ; DROP ; PACK } ] + - location: 294 (remaining gas: 1039156.857 units remaining) + [ { DUP ; DROP ; PACK } ] + - location: -1 (remaining gas: 1039156.812 units remaining) + [ { DUP ; DROP ; PACK } ] + - location: 299 (remaining gas: 1039156.732 units remaining) + [ { DUP ; DROP ; PACK } + { DUP ; DROP ; PACK } ] + - location: 300 (remaining gas: 1039143.362 units remaining) + [ 0x05020000000603210320030c @packed + { DUP ; DROP ; PACK } ] + - location: 303 (remaining gas: 1039129.917 units remaining) + [ 0x05020000000603210320030c @packed ] + - location: 304 (remaining gas: 1039078.027 units remaining) + [ (Some { DUP ; DROP ; PACK }) @packed.unpacked ] + - location: 314 (remaining gas: 1039077.892 units remaining) + [ { DUP ; DROP ; PACK } @packed.unpacked.some ] + - location: 308 (remaining gas: 1039077.847 units remaining) + [ { DUP ; DROP ; PACK } @packed.unpacked.some ] + - location: 315 (remaining gas: 1039064.477 units remaining) + [ 0x05020000000603210320030c @packed.unpacked.some.packed ] + - location: -1 (remaining gas: 1039064.432 units remaining) + [ 0x05020000000603210320030c @packed.unpacked.some.packed ] + - location: 301 (remaining gas: 1039064.432 units remaining) + [ 0x05020000000603210320030c @packed + 0x05020000000603210320030c @packed.unpacked.some.packed ] + - location: 318 (remaining gas: 1039064.222 units remaining) + [ 0 ] + - location: 319 (remaining gas: 1039064.147 units remaining) + [ True ] + - location: -1 (remaining gas: 1039064.102 units remaining) + [ True ] + - location: 321 (remaining gas: 1039064.002 units remaining) + [ ] + - location: -1 (remaining gas: 1039063.957 units remaining) + [ ] + - location: 326 (remaining gas: 1039063.882 units remaining) + [ Unit ] + - location: 327 (remaining gas: 1039063.807 units remaining) + [ {} + Unit ] + - location: 329 (remaining gas: 1039063.732 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039063.687 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair False False)-(Some (Pair False False))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair False False)-(Some (Pair False False))].out new file mode 100644 index 0000000000000000000000000000000000000000..72d03e1d28d4c1edd2773ed71c96d43a63a3411a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair False False)-(Some (Pair False False))].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair False False)-(Some (Pair False False))] + +storage + (Some (Pair False False)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039993.020 units remaining) + [ (Pair (Pair False False) None) ] + - location: 12 (remaining gas: 1039992.940 units remaining) + [ (Pair False False) @parameter ] + - location: 13 (remaining gas: 1039992.865 units remaining) + [ (Some (Pair False False)) ] + - location: 14 (remaining gas: 1039992.790 units remaining) + [ {} + (Some (Pair False False)) ] + - location: 16 (remaining gas: 1039992.715 units remaining) + [ (Pair {} (Some (Pair False False))) ] + - location: -1 (remaining gas: 1039992.670 units remaining) + [ (Pair {} (Some (Pair False False))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair False True)-(Some (Pair False True))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair False True)-(Some (Pair False True))].out new file mode 100644 index 0000000000000000000000000000000000000000..803194f7ea69ede90be60c578c39d3f61d2f014b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair False True)-(Some (Pair False True))].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair False True)-(Some (Pair False True))] + +storage + (Some (Pair False True)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039993.020 units remaining) + [ (Pair (Pair False True) None) ] + - location: 12 (remaining gas: 1039992.940 units remaining) + [ (Pair False True) @parameter ] + - location: 13 (remaining gas: 1039992.865 units remaining) + [ (Some (Pair False True)) ] + - location: 14 (remaining gas: 1039992.790 units remaining) + [ {} + (Some (Pair False True)) ] + - location: 16 (remaining gas: 1039992.715 units remaining) + [ (Pair {} (Some (Pair False True))) ] + - location: -1 (remaining gas: 1039992.670 units remaining) + [ (Pair {} (Some (Pair False True))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair True False)-(Some (Pair True False))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair True False)-(Some (Pair True False))].out new file mode 100644 index 0000000000000000000000000000000000000000..81ce92457c0edd49b7a226fd652699918abd5040 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair True False)-(Some (Pair True False))].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair True False)-(Some (Pair True False))] + +storage + (Some (Pair True False)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039993.020 units remaining) + [ (Pair (Pair True False) None) ] + - location: 12 (remaining gas: 1039992.940 units remaining) + [ (Pair True False) @parameter ] + - location: 13 (remaining gas: 1039992.865 units remaining) + [ (Some (Pair True False)) ] + - location: 14 (remaining gas: 1039992.790 units remaining) + [ {} + (Some (Pair True False)) ] + - location: 16 (remaining gas: 1039992.715 units remaining) + [ (Pair {} (Some (Pair True False))) ] + - location: -1 (remaining gas: 1039992.670 units remaining) + [ (Pair {} (Some (Pair True False))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair True True)-(Some (Pair True True))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair True True)-(Some (Pair True True))].out new file mode 100644 index 0000000000000000000000000000000000000000..1bcf7006333ac0ade2165b133a8953aa2d103e94 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair True True)-(Some (Pair True True))].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[pair_id.tz-None-(Pair True True)-(Some (Pair True True))] + +storage + (Some (Pair True True)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039993.020 units remaining) + [ (Pair (Pair True True) None) ] + - location: 12 (remaining gas: 1039992.940 units remaining) + [ (Pair True True) @parameter ] + - location: 13 (remaining gas: 1039992.865 units remaining) + [ (Some (Pair True True)) ] + - location: 14 (remaining gas: 1039992.790 units remaining) + [ {} + (Some (Pair True True)) ] + - location: 16 (remaining gas: 1039992.715 units remaining) + [ (Pair {} (Some (Pair True True))) ] + - location: -1 (remaining gas: 1039992.670 units remaining) + [ (Pair {} (Some (Pair True True))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pexec.tz-14-38-52].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pexec.tz-14-38-52].out new file mode 100644 index 0000000000000000000000000000000000000000..122f0e9688ef587eebd29c2bfc3ead40fbcf87a3 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pexec.tz-14-38-52].out @@ -0,0 +1,52 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[pexec.tz-14-38-52] + +storage + 52 +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039989.170 units remaining) + [ (Pair 38 14) ] + - location: 7 (remaining gas: 1039989.095 units remaining) + [ { UNPAIR ; ADD } + (Pair 38 14) ] + - location: 15 (remaining gas: 1039989.025 units remaining) + [ (Pair 38 14) + { UNPAIR ; ADD } ] + - location: 16 (remaining gas: 1039988.945 units remaining) + [ 38 @parameter + 14 @storage + { UNPAIR ; ADD } ] + - location: 19 (remaining gas: 1039987.515 units remaining) + [ { PUSH nat 14 ; PAIR ; { UNPAIR ; ADD } } ] + - location: 18 (remaining gas: 1039987.470 units remaining) + [ { PUSH nat 14 ; PAIR ; { UNPAIR ; ADD } } ] + - location: 17 (remaining gas: 1039987.470 units remaining) + [ 38 @parameter + { PUSH nat 14 ; PAIR ; { UNPAIR ; ADD } } ] + - location: 12 (remaining gas: 1039987.340 units remaining) + [ 38 ] + - location: 12 (remaining gas: 1039987.235 units remaining) + [ 14 + 38 ] + - location: 12 (remaining gas: 1039987.190 units remaining) + [ (Pair 14 38) ] + - location: 13 (remaining gas: 1039987.110 units remaining) + [ 14 + 38 ] + - location: 14 (remaining gas: 1039987 units remaining) + [ 52 ] + - location: -1 (remaining gas: 1039986.955 units remaining) + [ 52 ] + - location: 20 (remaining gas: 1039986.955 units remaining) + [ 52 ] + - location: 21 (remaining gas: 1039986.880 units remaining) + [ {} + 52 ] + - location: 23 (remaining gas: 1039986.805 units remaining) + [ (Pair {} 52) ] + - location: -1 (remaining gas: 1039986.760 units remaining) + [ (Pair {} 52) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pexec_2.tz-{ 0 ; 1 ; 2 ; 3}-4-{ 0 ; 7 ; 14 ; 21 }].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pexec_2.tz-{ 0 ; 1 ; 2 ; 3}-4-{ 0 ; 7 ; 14 ; 21 }].out new file mode 100644 index 0000000000000000000000000000000000000000..2c3849412a7daac3a062b288676f947cb620d179 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[pexec_2.tz-{ 0 ; 1 ; 2 ; 3}-4-{ 0 ; 7 ; 14 ; 21 }].out @@ -0,0 +1,314 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[pexec_2.tz-{ 0 ; 1 ; 2 ; 3}-4-{ 0 ; 7 ; 14 ; 21 }] + +storage + { 0 ; 7 ; 14 ; 21 } +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039978.900 units remaining) + [ (Pair 4 { 0 ; 1 ; 2 ; 3 }) ] + - location: 8 (remaining gas: 1039978.820 units remaining) + [ 4 @p + { 0 ; 1 ; 2 ; 3 } @s ] + - location: 9 (remaining gas: 1039978.745 units remaining) + [ { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } + 4 @p + { 0 ; 1 ; 2 ; 3 } @s ] + - location: 23 (remaining gas: 1039978.675 units remaining) + [ 4 @p + { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } + { 0 ; 1 ; 2 ; 3 } @s ] + - location: 24 (remaining gas: 1039977.320 units remaining) + [ { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } + { 0 ; 1 ; 2 ; 3 } @s ] + - location: 25 (remaining gas: 1039977.245 units remaining) + [ 3 + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } + { 0 ; 1 ; 2 ; 3 } @s ] + - location: 28 (remaining gas: 1039975.890 units remaining) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { 0 ; 1 ; 2 ; 3 } @s ] + - location: 29 (remaining gas: 1039975.820 units remaining) + [ { 0 ; 1 ; 2 ; 3 } @s + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 34 (remaining gas: 1039975.087 units remaining) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 33 (remaining gas: 1039975.042 units remaining) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (remaining gas: 1039975.042 units remaining) + [ 0 @s.elt + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 16 (remaining gas: 1039974.912 units remaining) + [ 0 ] + - location: 16 (remaining gas: 1039974.807 units remaining) + [ 3 + 0 ] + - location: 16 (remaining gas: 1039974.762 units remaining) + [ (Pair 3 0) ] + - location: 16 (remaining gas: 1039974.657 units remaining) + [ 4 + (Pair 3 0) ] + - location: 16 (remaining gas: 1039974.612 units remaining) + [ (Pair 4 3 0) ] + - location: 17 (remaining gas: 1039974.532 units remaining) + [ 4 + (Pair 3 0) ] + - location: 20 (remaining gas: 1039974.377 units remaining) + [ 3 + 0 ] + - location: 19 (remaining gas: 1039974.332 units remaining) + [ 3 + 0 ] + - location: 18 (remaining gas: 1039974.332 units remaining) + [ 4 + 3 + 0 ] + - location: 21 (remaining gas: 1039974.222 units remaining) + [ 7 + 0 ] + - location: 22 (remaining gas: 1039974.110 units remaining) + [ 0 ] + - location: -1 (remaining gas: 1039974.065 units remaining) + [ 0 ] + - location: 35 (remaining gas: 1039974.065 units remaining) + [ 0 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: -1 (remaining gas: 1039974.020 units remaining) + [ 0 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 34 (remaining gas: 1039973.865 units remaining) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 33 (remaining gas: 1039973.820 units remaining) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (remaining gas: 1039973.820 units remaining) + [ 1 @s.elt + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 16 (remaining gas: 1039973.690 units remaining) + [ 1 ] + - location: 16 (remaining gas: 1039973.585 units remaining) + [ 3 + 1 ] + - location: 16 (remaining gas: 1039973.540 units remaining) + [ (Pair 3 1) ] + - location: 16 (remaining gas: 1039973.435 units remaining) + [ 4 + (Pair 3 1) ] + - location: 16 (remaining gas: 1039973.390 units remaining) + [ (Pair 4 3 1) ] + - location: 17 (remaining gas: 1039973.310 units remaining) + [ 4 + (Pair 3 1) ] + - location: 20 (remaining gas: 1039973.155 units remaining) + [ 3 + 1 ] + - location: 19 (remaining gas: 1039973.110 units remaining) + [ 3 + 1 ] + - location: 18 (remaining gas: 1039973.110 units remaining) + [ 4 + 3 + 1 ] + - location: 21 (remaining gas: 1039973 units remaining) + [ 7 + 1 ] + - location: 22 (remaining gas: 1039972.884 units remaining) + [ 7 ] + - location: -1 (remaining gas: 1039972.839 units remaining) + [ 7 ] + - location: 35 (remaining gas: 1039972.839 units remaining) + [ 7 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: -1 (remaining gas: 1039972.794 units remaining) + [ 7 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 34 (remaining gas: 1039972.639 units remaining) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 33 (remaining gas: 1039972.594 units remaining) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (remaining gas: 1039972.594 units remaining) + [ 2 @s.elt + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 16 (remaining gas: 1039972.464 units remaining) + [ 2 ] + - location: 16 (remaining gas: 1039972.359 units remaining) + [ 3 + 2 ] + - location: 16 (remaining gas: 1039972.314 units remaining) + [ (Pair 3 2) ] + - location: 16 (remaining gas: 1039972.209 units remaining) + [ 4 + (Pair 3 2) ] + - location: 16 (remaining gas: 1039972.164 units remaining) + [ (Pair 4 3 2) ] + - location: 17 (remaining gas: 1039972.084 units remaining) + [ 4 + (Pair 3 2) ] + - location: 20 (remaining gas: 1039971.929 units remaining) + [ 3 + 2 ] + - location: 19 (remaining gas: 1039971.884 units remaining) + [ 3 + 2 ] + - location: 18 (remaining gas: 1039971.884 units remaining) + [ 4 + 3 + 2 ] + - location: 21 (remaining gas: 1039971.774 units remaining) + [ 7 + 2 ] + - location: 22 (remaining gas: 1039971.658 units remaining) + [ 14 ] + - location: -1 (remaining gas: 1039971.613 units remaining) + [ 14 ] + - location: 35 (remaining gas: 1039971.613 units remaining) + [ 14 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: -1 (remaining gas: 1039971.568 units remaining) + [ 14 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 34 (remaining gas: 1039971.413 units remaining) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 33 (remaining gas: 1039971.368 units remaining) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (remaining gas: 1039971.368 units remaining) + [ 3 @s.elt + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 16 (remaining gas: 1039971.238 units remaining) + [ 3 ] + - location: 16 (remaining gas: 1039971.133 units remaining) + [ 3 + 3 ] + - location: 16 (remaining gas: 1039971.088 units remaining) + [ (Pair 3 3) ] + - location: 16 (remaining gas: 1039970.983 units remaining) + [ 4 + (Pair 3 3) ] + - location: 16 (remaining gas: 1039970.938 units remaining) + [ (Pair 4 3 3) ] + - location: 17 (remaining gas: 1039970.858 units remaining) + [ 4 + (Pair 3 3) ] + - location: 20 (remaining gas: 1039970.703 units remaining) + [ 3 + 3 ] + - location: 19 (remaining gas: 1039970.658 units remaining) + [ 3 + 3 ] + - location: 18 (remaining gas: 1039970.658 units remaining) + [ 4 + 3 + 3 ] + - location: 21 (remaining gas: 1039970.548 units remaining) + [ 7 + 3 ] + - location: 22 (remaining gas: 1039970.432 units remaining) + [ 21 ] + - location: -1 (remaining gas: 1039970.387 units remaining) + [ 21 ] + - location: 35 (remaining gas: 1039970.387 units remaining) + [ 21 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: -1 (remaining gas: 1039970.342 units remaining) + [ 21 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 30 (remaining gas: 1039970.342 units remaining) + [ { 0 ; 7 ; 14 ; 21 } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 38 (remaining gas: 1039970.192 units remaining) + [ ] + - location: 37 (remaining gas: 1039970.147 units remaining) + [ ] + - location: 36 (remaining gas: 1039970.147 units remaining) + [ { 0 ; 7 ; 14 ; 21 } ] + - location: 39 (remaining gas: 1039970.072 units remaining) + [ {} + { 0 ; 7 ; 14 ; 21 } ] + - location: 41 (remaining gas: 1039969.997 units remaining) + [ (Pair {} { 0 ; 7 ; 14 ; 21 }) ] + - location: -1 (remaining gas: 1039969.952 units remaining) + [ (Pair {} { 0 ; 7 ; 14 ; 21 }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ret_int.tz-None-Unit-(Some 300)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ret_int.tz-None-Unit-(Some 300)].out new file mode 100644 index 0000000000000000000000000000000000000000..f71c22b8037aaedb7c103c040d0d0c6d04c906ad --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[ret_int.tz-None-Unit-(Some 300)].out @@ -0,0 +1,25 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[ret_int.tz-None-Unit-(Some 300)] + +storage + (Some 300) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.280 units remaining) + [ (Pair Unit None) ] + - location: 8 (remaining gas: 1039993.205 units remaining) + [ ] + - location: 9 (remaining gas: 1039993.130 units remaining) + [ 300 ] + - location: 12 (remaining gas: 1039993.055 units remaining) + [ (Some 300) ] + - location: 13 (remaining gas: 1039992.980 units remaining) + [ {} + (Some 300) ] + - location: 15 (remaining gas: 1039992.905 units remaining) + [ (Pair {} (Some 300)) ] + - location: -1 (remaining gas: 1039992.860 units remaining) + [ (Pair {} (Some 300)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse.tz-{\"\"}-{ \"c\" ; \"b\" ; \"a\" }-{ \"a\" ; \"b\" ; \"c\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse.tz-{\"\"}-{ \"c\" ; \"b\" ; \"a\" }-{ \"a\" ; \"b\" ; \"c\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..3c5797db28f19e5562907225eaf46a14d1cfe9b9 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse.tz-{\"\"}-{ \"c\" ; \"b\" ; \"a\" }-{ \"a\" ; \"b\" ; \"c\" }].out" @@ -0,0 +1,41 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[reverse.tz-{""}-{ "c" ; "b" ; "a" }-{ "a" ; "b" ; "c" }] + +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039990.414 units remaining) + [ (Pair { "c" ; "b" ; "a" } { "" }) ] + - location: 9 (remaining gas: 1039990.334 units remaining) + [ { "c" ; "b" ; "a" } @parameter ] + - location: 10 (remaining gas: 1039990.259 units remaining) + [ {} + { "c" ; "b" ; "a" } @parameter ] + - location: 12 (remaining gas: 1039990.189 units remaining) + [ { "c" ; "b" ; "a" } @parameter + {} ] + - location: 15 (remaining gas: 1039989.558 units remaining) + [ { "c" } ] + - location: 14 (remaining gas: 1039989.513 units remaining) + [ { "c" } ] + - location: 15 (remaining gas: 1039989.433 units remaining) + [ { "b" ; "c" } ] + - location: 14 (remaining gas: 1039989.388 units remaining) + [ { "b" ; "c" } ] + - location: 15 (remaining gas: 1039989.308 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 14 (remaining gas: 1039989.263 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 13 (remaining gas: 1039989.263 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 16 (remaining gas: 1039989.188 units remaining) + [ {} + { "a" ; "b" ; "c" } ] + - location: 18 (remaining gas: 1039989.113 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: -1 (remaining gas: 1039989.068 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse.tz-{\"\"}-{}-{}].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse.tz-{\"\"}-{}-{}].out" new file mode 100644 index 0000000000000000000000000000000000000000..fa055fd1380925dc8fbd70abb4cff388c86fced9 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse.tz-{\"\"}-{}-{}].out" @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[reverse.tz-{""}-{}-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039991.206 units remaining) + [ (Pair {} { "" }) ] + - location: 9 (remaining gas: 1039991.126 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039991.051 units remaining) + [ {} + {} @parameter ] + - location: 12 (remaining gas: 1039990.981 units remaining) + [ {} @parameter + {} ] + - location: 13 (remaining gas: 1039990.451 units remaining) + [ {} ] + - location: 16 (remaining gas: 1039990.376 units remaining) + [ {} + {} ] + - location: 18 (remaining gas: 1039990.301 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039990.256 units remaining) + [ (Pair {} {}) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse_loop.tz-{\"\"}-{ \"c\" ; \"b\" ; \"a\" }-{ \"a\" ; \"b\" ; \"c\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse_loop.tz-{\"\"}-{ \"c\" ; \"b\" ; \"a\" }-{ \"a\" ; \"b\" ; \"c\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..3d13024bab0182f906caa853ad7c75e1943af367 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse_loop.tz-{\"\"}-{ \"c\" ; \"b\" ; \"a\" }-{ \"a\" ; \"b\" ; \"c\" }].out" @@ -0,0 +1,120 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[reverse_loop.tz-{""}-{ "c" ; "b" ; "a" }-{ "a" ; "b" ; "c" }] + +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039981.974 units remaining) + [ (Pair { "c" ; "b" ; "a" } { "" }) ] + - location: 9 (remaining gas: 1039981.894 units remaining) + [ { "c" ; "b" ; "a" } @parameter ] + - location: 10 (remaining gas: 1039981.819 units remaining) + [ {} + { "c" ; "b" ; "a" } @parameter ] + - location: 12 (remaining gas: 1039981.749 units remaining) + [ { "c" ; "b" ; "a" } @parameter + {} ] + - location: 13 (remaining gas: 1039981.674 units remaining) + [ True + { "c" ; "b" ; "a" } @parameter + {} ] + - location: 20 (remaining gas: 1039981.474 units remaining) + [ { "b" ; "a" } @parameter.tl + "c" @parameter.hd + {} ] + - location: 23 (remaining gas: 1039981.319 units remaining) + [ { "c" } ] + - location: 22 (remaining gas: 1039981.274 units remaining) + [ { "c" } ] + - location: 21 (remaining gas: 1039981.274 units remaining) + [ { "b" ; "a" } @parameter.tl + { "c" } ] + - location: 24 (remaining gas: 1039981.199 units remaining) + [ True + { "b" ; "a" } @parameter.tl + { "c" } ] + - location: -1 (remaining gas: 1039981.154 units remaining) + [ True + { "b" ; "a" } @parameter.tl + { "c" } ] + - location: 17 (remaining gas: 1039981.109 units remaining) + [ True + { "b" ; "a" } + { "c" } ] + - location: 20 (remaining gas: 1039980.939 units remaining) + [ { "a" } @parameter.tl + "b" @parameter.hd + { "c" } ] + - location: 23 (remaining gas: 1039980.784 units remaining) + [ { "b" ; "c" } ] + - location: 22 (remaining gas: 1039980.739 units remaining) + [ { "b" ; "c" } ] + - location: 21 (remaining gas: 1039980.739 units remaining) + [ { "a" } @parameter.tl + { "b" ; "c" } ] + - location: 24 (remaining gas: 1039980.664 units remaining) + [ True + { "a" } @parameter.tl + { "b" ; "c" } ] + - location: -1 (remaining gas: 1039980.619 units remaining) + [ True + { "a" } @parameter.tl + { "b" ; "c" } ] + - location: 17 (remaining gas: 1039980.574 units remaining) + [ True + { "a" } + { "b" ; "c" } ] + - location: 20 (remaining gas: 1039980.404 units remaining) + [ {} @parameter.tl + "a" @parameter.hd + { "b" ; "c" } ] + - location: 23 (remaining gas: 1039980.249 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 22 (remaining gas: 1039980.204 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 21 (remaining gas: 1039980.204 units remaining) + [ {} @parameter.tl + { "a" ; "b" ; "c" } ] + - location: 24 (remaining gas: 1039980.129 units remaining) + [ True + {} @parameter.tl + { "a" ; "b" ; "c" } ] + - location: -1 (remaining gas: 1039980.084 units remaining) + [ True + {} @parameter.tl + { "a" ; "b" ; "c" } ] + - location: 17 (remaining gas: 1039980.039 units remaining) + [ True + {} + { "a" ; "b" ; "c" } ] + - location: 28 (remaining gas: 1039979.864 units remaining) + [ {} + { "a" ; "b" ; "c" } ] + - location: 30 (remaining gas: 1039979.789 units remaining) + [ False + {} + { "a" ; "b" ; "c" } ] + - location: -1 (remaining gas: 1039979.744 units remaining) + [ False + {} + { "a" ; "b" ; "c" } ] + - location: 17 (remaining gas: 1039979.699 units remaining) + [ False + {} + { "a" ; "b" ; "c" } ] + - location: 16 (remaining gas: 1039979.659 units remaining) + [ {} @parameter + { "a" ; "b" ; "c" } ] + - location: 33 (remaining gas: 1039979.584 units remaining) + [ { "a" ; "b" ; "c" } ] + - location: 34 (remaining gas: 1039979.509 units remaining) + [ {} + { "a" ; "b" ; "c" } ] + - location: 36 (remaining gas: 1039979.434 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: -1 (remaining gas: 1039979.389 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse_loop.tz-{\"\"}-{}-{}].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse_loop.tz-{\"\"}-{}-{}].out" new file mode 100644 index 0000000000000000000000000000000000000000..bef14a4f1654eed9af4bfb5c1292357949039e2c --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[reverse_loop.tz-{\"\"}-{}-{}].out" @@ -0,0 +1,51 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[reverse_loop.tz-{""}-{}-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039982.766 units remaining) + [ (Pair {} { "" }) ] + - location: 9 (remaining gas: 1039982.686 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039982.611 units remaining) + [ {} + {} @parameter ] + - location: 12 (remaining gas: 1039982.541 units remaining) + [ {} @parameter + {} ] + - location: 13 (remaining gas: 1039982.466 units remaining) + [ True + {} @parameter + {} ] + - location: 28 (remaining gas: 1039982.261 units remaining) + [ {} + {} ] + - location: 30 (remaining gas: 1039982.186 units remaining) + [ False + {} + {} ] + - location: -1 (remaining gas: 1039982.141 units remaining) + [ False + {} + {} ] + - location: 17 (remaining gas: 1039982.096 units remaining) + [ False + {} + {} ] + - location: 16 (remaining gas: 1039982.056 units remaining) + [ {} @parameter + {} ] + - location: 33 (remaining gas: 1039981.981 units remaining) + [ {} ] + - location: 34 (remaining gas: 1039981.906 units remaining) + [ {} + {} ] + - location: 36 (remaining gas: 1039981.831 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039981.786 units remaining) + [ (Pair {} {}) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sapling_empty_state.tz-{}-Unit-0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sapling_empty_state.tz-{}-Unit-0].out new file mode 100644 index 0000000000000000000000000000000000000000..760dc9c1d9a72d0e179b7fa71d19eaf08eceb700 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sapling_empty_state.tz-{}-Unit-0].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[sapling_empty_state.tz-{}-Unit-0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.740 units remaining) + [ (Pair Unit {}) ] + - location: 8 (remaining gas: 1039994.665 units remaining) + [ ] + - location: 9 (remaining gas: 1039994.435 units remaining) + [ {} @sapling ] + - location: 11 (remaining gas: 1039994.360 units remaining) + [ {} + {} @sapling ] + - location: 13 (remaining gas: 1039994.285 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039994.240 units remaining) + [ (Pair {} {}) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[self_address.tz-Unit-Unit-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[self_address.tz-Unit-Unit-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..beefdf902d42bf293c97e204a1042d03ee6bee42 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[self_address.tz-Unit-Unit-Unit].out @@ -0,0 +1,54 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[self_address.tz-Unit-Unit-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039983.390 units remaining) + [ (Pair Unit Unit) ] + - location: 7 (remaining gas: 1039983.315 units remaining) + [ ] + - location: 8 (remaining gas: 1039983.240 units remaining) + [ { DROP ; SELF_ADDRESS } ] + - location: 14 (remaining gas: 1039983.165 units remaining) + [ Unit + { DROP ; SELF_ADDRESS } ] + - location: 11 (remaining gas: 1039983.035 units remaining) + [ Unit @arg ] + - location: 12 (remaining gas: 1039982.960 units remaining) + [ ] + - location: 13 (remaining gas: 1039982.885 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self ] + - location: -1 (remaining gas: 1039982.840 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self ] + - location: 15 (remaining gas: 1039982.840 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 16 (remaining gas: 1039982.765 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self + "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 17 (remaining gas: 1039982.690 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self.address + "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 20 (remaining gas: 1039982.382 units remaining) + [ 0 ] + - location: 21 (remaining gas: 1039982.307 units remaining) + [ True ] + - location: -1 (remaining gas: 1039982.262 units remaining) + [ True ] + - location: 23 (remaining gas: 1039982.162 units remaining) + [ ] + - location: -1 (remaining gas: 1039982.117 units remaining) + [ ] + - location: 28 (remaining gas: 1039982.042 units remaining) + [ Unit ] + - location: 29 (remaining gas: 1039981.967 units remaining) + [ {} + Unit ] + - location: 31 (remaining gas: 1039981.892 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039981.847 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[self_with_default_entrypoint.tz-Unit-Unit-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[self_with_default_entrypoint.tz-Unit-Unit-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..845919118ce4199baa39c59d8ae09c580dcbe834 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[self_with_default_entrypoint.tz-Unit-Unit-Unit].out @@ -0,0 +1,51 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[self_with_default_entrypoint.tz-Unit-Unit-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 12 (remaining gas: 1039981.740 units remaining) + [ (Pair (Right (Left Unit)) Unit) ] + - location: 13 (remaining gas: 1039981.665 units remaining) + [ ] + - location: 14 (remaining gas: 1039981.590 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self ] + - location: 15 (remaining gas: 1039981.515 units remaining) + [ ] + - location: 16 (remaining gas: 1039981.440 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%A" @self ] + - location: 17 (remaining gas: 1039981.365 units remaining) + [ ] + - location: 18 (remaining gas: 1039981.290 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self ] + - location: 19 (remaining gas: 1039950.420 units remaining) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @self.packed ] + - location: 20 (remaining gas: 1039950.345 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @self.packed ] + - location: 21 (remaining gas: 1039919.475 units remaining) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @self.packed + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @self.packed ] + - location: 24 (remaining gas: 1039919.265 units remaining) + [ 0 ] + - location: 25 (remaining gas: 1039919.190 units remaining) + [ True ] + - location: -1 (remaining gas: 1039919.145 units remaining) + [ True ] + - location: 27 (remaining gas: 1039919.045 units remaining) + [ ] + - location: -1 (remaining gas: 1039919 units remaining) + [ ] + - location: 32 (remaining gas: 1039918.925 units remaining) + [ Unit ] + - location: 33 (remaining gas: 1039918.850 units remaining) + [ {} + Unit ] + - location: 35 (remaining gas: 1039918.775 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039918.730 units remaining) + [ (Pair {} Unit) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[self_with_entrypoint.tz-Unit-Left (Left 0)-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[self_with_entrypoint.tz-Unit-Left (Left 0)-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..a95c76b8aae6fc109c07db97a7a5394ac0363ccb --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[self_with_entrypoint.tz-Unit-Left (Left 0)-Unit].out @@ -0,0 +1,112 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[self_with_entrypoint.tz-Unit-Left (Left 0)-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 12 (remaining gas: 1039953.950 units remaining) + [ (Pair (Left (Left 0)) Unit) ] + - location: 13 (remaining gas: 1039953.875 units remaining) + [ ] + - location: 14 (remaining gas: 1039953.800 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%A" @self ] + - location: 15 (remaining gas: 1039922.930 units remaining) + [ 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 @Apacked ] + - location: 16 (remaining gas: 1039922.855 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self + 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 @Apacked ] + - location: 17 (remaining gas: 1039891.985 units remaining) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked + 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 @Apacked ] + - location: 18 (remaining gas: 1039891.905 units remaining) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked + 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 @Apacked ] + - location: 21 (remaining gas: 1039891.760 units remaining) + [ 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 @Apacked + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: 20 (remaining gas: 1039891.715 units remaining) + [ 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 @Apacked + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: 19 (remaining gas: 1039891.715 units remaining) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked + 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 @Apacked + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: 24 (remaining gas: 1039891.505 units remaining) + [ -1 + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: 25 (remaining gas: 1039891.430 units remaining) + [ True + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: -1 (remaining gas: 1039891.385 units remaining) + [ True + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: 27 (remaining gas: 1039891.285 units remaining) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: -1 (remaining gas: 1039891.240 units remaining) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: 32 (remaining gas: 1039891.165 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: 33 (remaining gas: 1039860.295 units remaining) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @selfpacked + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 @defpacked ] + - location: 36 (remaining gas: 1039860.085 units remaining) + [ 0 ] + - location: 37 (remaining gas: 1039860.010 units remaining) + [ True ] + - location: -1 (remaining gas: 1039859.965 units remaining) + [ True ] + - location: 39 (remaining gas: 1039859.865 units remaining) + [ ] + - location: -1 (remaining gas: 1039859.820 units remaining) + [ ] + - location: 44 (remaining gas: 1039859.745 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%A" @self ] + - location: 45 (remaining gas: 1039859.670 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%A" @self ] + - location: 48 (remaining gas: 1039859.595 units remaining) + [ ] + - location: 49 (remaining gas: 1039859.520 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%B" @self ] + - location: 50 (remaining gas: 1039859.445 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%B" @self ] + - location: 53 (remaining gas: 1039859.370 units remaining) + [ ] + - location: 54 (remaining gas: 1039859.295 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%maybe_C" @self ] + - location: 55 (remaining gas: 1039859.220 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%maybe_C" @self ] + - location: 60 (remaining gas: 1039859.145 units remaining) + [ ] + - location: 61 (remaining gas: 1039859.070 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%Z" @self ] + - location: 62 (remaining gas: 1039858.995 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%Z" @self ] + - location: 65 (remaining gas: 1039858.920 units remaining) + [ ] + - location: 66 (remaining gas: 1039858.845 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self ] + - location: 67 (remaining gas: 1039858.770 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self ] + - location: 76 (remaining gas: 1039858.695 units remaining) + [ ] + - location: 77 (remaining gas: 1039858.620 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self ] + - location: 78 (remaining gas: 1039858.545 units remaining) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" @self ] + - location: 87 (remaining gas: 1039858.470 units remaining) + [ ] + - location: 88 (remaining gas: 1039858.395 units remaining) + [ Unit ] + - location: 89 (remaining gas: 1039858.320 units remaining) + [ {} + Unit ] + - location: 91 (remaining gas: 1039858.245 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039858.200 units remaining) + [ (Pair {} Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair \"hello\" 0)-\"\"-(Pair \"\" 0)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair \"hello\" 0)-\"\"-(Pair \"\" 0)].out" new file mode 100644 index 0000000000000000000000000000000000000000..08f2393bf751e60ca4aa2469dc098491c7c3186b --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair \"hello\" 0)-\"\"-(Pair \"\" 0)].out" @@ -0,0 +1,53 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair "hello" 0)-""-(Pair "" 0)] + +storage + (Pair "" 0) +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039985.287 units remaining) + [ (Pair "" "hello" 0) ] + - location: 9 (remaining gas: 1039985.207 units remaining) + [ (Pair "" "hello" 0) + (Pair "" "hello" 0) ] + - location: 10 (remaining gas: 1039985.127 units remaining) + [ (Pair "hello" 0) @storage + (Pair "" "hello" 0) ] + - location: 13 (remaining gas: 1039984.972 units remaining) + [ "" @parameter ] + - location: 12 (remaining gas: 1039984.927 units remaining) + [ "" @parameter ] + - location: 11 (remaining gas: 1039984.927 units remaining) + [ (Pair "hello" 0) @storage + "" @parameter ] + - location: 15 (remaining gas: 1039984.817 units remaining) + [ (Pair "hello" 0) @storage + (Pair "hello" 0) @storage + "" @parameter ] + - location: 16 (remaining gas: 1039984.737 units remaining) + [ "hello" + (Pair "hello" 0) @storage + "" @parameter ] + - location: 17 (remaining gas: 1039984.662 units remaining) + [ (Pair "hello" 0) @storage + "" @parameter ] + - location: 18 (remaining gas: 1039984.582 units remaining) + [ 0 @storage.n + "" @parameter ] + - location: 19 (remaining gas: 1039984.512 units remaining) + [ "" @parameter + 0 @storage.n ] + - location: 20 (remaining gas: 1039984.437 units remaining) + [ (Pair "" 0) @storage ] + - location: -1 (remaining gas: 1039984.392 units remaining) + [ (Pair "" 0) @storage ] + - location: 21 (remaining gas: 1039984.317 units remaining) + [ {} + (Pair "" 0) @storage ] + - location: 23 (remaining gas: 1039984.242 units remaining) + [ (Pair {} "" 0) ] + - location: -1 (remaining gas: 1039984.197 units remaining) + [ (Pair {} "" 0) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair \"hello\" 0)-\"abc\"-(Pair \"abc\" 0)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair \"hello\" 0)-\"abc\"-(Pair \"abc\" 0)].out" new file mode 100644 index 0000000000000000000000000000000000000000..7a16df39b83979f8ec776da36b1b064dabb1ec11 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair \"hello\" 0)-\"abc\"-(Pair \"abc\" 0)].out" @@ -0,0 +1,53 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair "hello" 0)-"abc"-(Pair "abc" 0)] + +storage + (Pair "abc" 0) +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039985.257 units remaining) + [ (Pair "abc" "hello" 0) ] + - location: 9 (remaining gas: 1039985.177 units remaining) + [ (Pair "abc" "hello" 0) + (Pair "abc" "hello" 0) ] + - location: 10 (remaining gas: 1039985.097 units remaining) + [ (Pair "hello" 0) @storage + (Pair "abc" "hello" 0) ] + - location: 13 (remaining gas: 1039984.942 units remaining) + [ "abc" @parameter ] + - location: 12 (remaining gas: 1039984.897 units remaining) + [ "abc" @parameter ] + - location: 11 (remaining gas: 1039984.897 units remaining) + [ (Pair "hello" 0) @storage + "abc" @parameter ] + - location: 15 (remaining gas: 1039984.787 units remaining) + [ (Pair "hello" 0) @storage + (Pair "hello" 0) @storage + "abc" @parameter ] + - location: 16 (remaining gas: 1039984.707 units remaining) + [ "hello" + (Pair "hello" 0) @storage + "abc" @parameter ] + - location: 17 (remaining gas: 1039984.632 units remaining) + [ (Pair "hello" 0) @storage + "abc" @parameter ] + - location: 18 (remaining gas: 1039984.552 units remaining) + [ 0 @storage.n + "abc" @parameter ] + - location: 19 (remaining gas: 1039984.482 units remaining) + [ "abc" @parameter + 0 @storage.n ] + - location: 20 (remaining gas: 1039984.407 units remaining) + [ (Pair "abc" 0) @storage ] + - location: -1 (remaining gas: 1039984.362 units remaining) + [ (Pair "abc" 0) @storage ] + - location: 21 (remaining gas: 1039984.287 units remaining) + [ {} + (Pair "abc" 0) @storage ] + - location: 23 (remaining gas: 1039984.212 units remaining) + [ (Pair {} "abc" 0) ] + - location: -1 (remaining gas: 1039984.167 units remaining) + [ (Pair {} "abc" 0) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair \"hello\" 0)-\"world\"-(Pair \"world\" 0)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair \"hello\" 0)-\"world\"-(Pair \"world\" 0)].out" new file mode 100644 index 0000000000000000000000000000000000000000..20818dfbdce911efa829522f1df01eff04b742b0 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair \"hello\" 0)-\"world\"-(Pair \"world\" 0)].out" @@ -0,0 +1,53 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_car.tz-(Pair "hello" 0)-"world"-(Pair "world" 0)] + +storage + (Pair "world" 0) +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039985.237 units remaining) + [ (Pair "world" "hello" 0) ] + - location: 9 (remaining gas: 1039985.157 units remaining) + [ (Pair "world" "hello" 0) + (Pair "world" "hello" 0) ] + - location: 10 (remaining gas: 1039985.077 units remaining) + [ (Pair "hello" 0) @storage + (Pair "world" "hello" 0) ] + - location: 13 (remaining gas: 1039984.922 units remaining) + [ "world" @parameter ] + - location: 12 (remaining gas: 1039984.877 units remaining) + [ "world" @parameter ] + - location: 11 (remaining gas: 1039984.877 units remaining) + [ (Pair "hello" 0) @storage + "world" @parameter ] + - location: 15 (remaining gas: 1039984.767 units remaining) + [ (Pair "hello" 0) @storage + (Pair "hello" 0) @storage + "world" @parameter ] + - location: 16 (remaining gas: 1039984.687 units remaining) + [ "hello" + (Pair "hello" 0) @storage + "world" @parameter ] + - location: 17 (remaining gas: 1039984.612 units remaining) + [ (Pair "hello" 0) @storage + "world" @parameter ] + - location: 18 (remaining gas: 1039984.532 units remaining) + [ 0 @storage.n + "world" @parameter ] + - location: 19 (remaining gas: 1039984.462 units remaining) + [ "world" @parameter + 0 @storage.n ] + - location: 20 (remaining gas: 1039984.387 units remaining) + [ (Pair "world" 0) @storage ] + - location: -1 (remaining gas: 1039984.342 units remaining) + [ (Pair "world" 0) @storage ] + - location: 21 (remaining gas: 1039984.267 units remaining) + [ {} + (Pair "world" 0) @storage ] + - location: 23 (remaining gas: 1039984.192 units remaining) + [ (Pair {} "world" 0) ] + - location: -1 (remaining gas: 1039984.147 units remaining) + [ (Pair {} "world" 0) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair \"hello\" 0)-1-(Pair \"hello\" 1)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair \"hello\" 0)-1-(Pair \"hello\" 1)].out" new file mode 100644 index 0000000000000000000000000000000000000000..b42bb2fdda74ac64d73d42050af374bab4f62eec --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair \"hello\" 0)-1-(Pair \"hello\" 1)].out" @@ -0,0 +1,50 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair "hello" 0)-1-(Pair "hello" 1)] + +storage + (Pair "hello" 1) +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039986.051 units remaining) + [ (Pair 1 "hello" 0) ] + - location: 9 (remaining gas: 1039985.971 units remaining) + [ (Pair 1 "hello" 0) + (Pair 1 "hello" 0) ] + - location: 10 (remaining gas: 1039985.891 units remaining) + [ (Pair "hello" 0) @storage + (Pair 1 "hello" 0) ] + - location: 13 (remaining gas: 1039985.736 units remaining) + [ 1 @parameter ] + - location: 12 (remaining gas: 1039985.691 units remaining) + [ 1 @parameter ] + - location: 11 (remaining gas: 1039985.691 units remaining) + [ (Pair "hello" 0) @storage + 1 @parameter ] + - location: 15 (remaining gas: 1039985.581 units remaining) + [ (Pair "hello" 0) @storage + (Pair "hello" 0) @storage + 1 @parameter ] + - location: 16 (remaining gas: 1039985.501 units remaining) + [ 0 + (Pair "hello" 0) @storage + 1 @parameter ] + - location: 17 (remaining gas: 1039985.426 units remaining) + [ (Pair "hello" 0) @storage + 1 @parameter ] + - location: 18 (remaining gas: 1039985.346 units remaining) + [ "hello" @storage.s + 1 @parameter ] + - location: 19 (remaining gas: 1039985.271 units remaining) + [ (Pair "hello" 1) @storage ] + - location: -1 (remaining gas: 1039985.226 units remaining) + [ (Pair "hello" 1) @storage ] + - location: 20 (remaining gas: 1039985.151 units remaining) + [ {} + (Pair "hello" 1) @storage ] + - location: 22 (remaining gas: 1039985.076 units remaining) + [ (Pair {} "hello" 1) ] + - location: -1 (remaining gas: 1039985.031 units remaining) + [ (Pair {} "hello" 1) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair \"hello\" 500)-3-(Pair \"hello\" 3)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair \"hello\" 500)-3-(Pair \"hello\" 3)].out" new file mode 100644 index 0000000000000000000000000000000000000000..52e646e04b6ce54619327deb83e8716dbdcd414f --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair \"hello\" 500)-3-(Pair \"hello\" 3)].out" @@ -0,0 +1,50 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair "hello" 500)-3-(Pair "hello" 3)] + +storage + (Pair "hello" 3) +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039986.051 units remaining) + [ (Pair 3 "hello" 500) ] + - location: 9 (remaining gas: 1039985.971 units remaining) + [ (Pair 3 "hello" 500) + (Pair 3 "hello" 500) ] + - location: 10 (remaining gas: 1039985.891 units remaining) + [ (Pair "hello" 500) @storage + (Pair 3 "hello" 500) ] + - location: 13 (remaining gas: 1039985.736 units remaining) + [ 3 @parameter ] + - location: 12 (remaining gas: 1039985.691 units remaining) + [ 3 @parameter ] + - location: 11 (remaining gas: 1039985.691 units remaining) + [ (Pair "hello" 500) @storage + 3 @parameter ] + - location: 15 (remaining gas: 1039985.581 units remaining) + [ (Pair "hello" 500) @storage + (Pair "hello" 500) @storage + 3 @parameter ] + - location: 16 (remaining gas: 1039985.501 units remaining) + [ 500 + (Pair "hello" 500) @storage + 3 @parameter ] + - location: 17 (remaining gas: 1039985.426 units remaining) + [ (Pair "hello" 500) @storage + 3 @parameter ] + - location: 18 (remaining gas: 1039985.346 units remaining) + [ "hello" @storage.s + 3 @parameter ] + - location: 19 (remaining gas: 1039985.271 units remaining) + [ (Pair "hello" 3) @storage ] + - location: -1 (remaining gas: 1039985.226 units remaining) + [ (Pair "hello" 3) @storage ] + - location: 20 (remaining gas: 1039985.151 units remaining) + [ {} + (Pair "hello" 3) @storage ] + - location: 22 (remaining gas: 1039985.076 units remaining) + [ (Pair {} "hello" 3) ] + - location: -1 (remaining gas: 1039985.031 units remaining) + [ (Pair {} "hello" 3) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair \"hello\" 7)-100-(Pair \"hello\" 100)].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair \"hello\" 7)-100-(Pair \"hello\" 100)].out" new file mode 100644 index 0000000000000000000000000000000000000000..268fed6b595cb38372b90c3ef5bf2e9008349bd9 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair \"hello\" 7)-100-(Pair \"hello\" 100)].out" @@ -0,0 +1,50 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_cdr.tz-(Pair "hello" 7)-100-(Pair "hello" 100)] + +storage + (Pair "hello" 100) +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039986.051 units remaining) + [ (Pair 100 "hello" 7) ] + - location: 9 (remaining gas: 1039985.971 units remaining) + [ (Pair 100 "hello" 7) + (Pair 100 "hello" 7) ] + - location: 10 (remaining gas: 1039985.891 units remaining) + [ (Pair "hello" 7) @storage + (Pair 100 "hello" 7) ] + - location: 13 (remaining gas: 1039985.736 units remaining) + [ 100 @parameter ] + - location: 12 (remaining gas: 1039985.691 units remaining) + [ 100 @parameter ] + - location: 11 (remaining gas: 1039985.691 units remaining) + [ (Pair "hello" 7) @storage + 100 @parameter ] + - location: 15 (remaining gas: 1039985.581 units remaining) + [ (Pair "hello" 7) @storage + (Pair "hello" 7) @storage + 100 @parameter ] + - location: 16 (remaining gas: 1039985.501 units remaining) + [ 7 + (Pair "hello" 7) @storage + 100 @parameter ] + - location: 17 (remaining gas: 1039985.426 units remaining) + [ (Pair "hello" 7) @storage + 100 @parameter ] + - location: 18 (remaining gas: 1039985.346 units remaining) + [ "hello" @storage.s + 100 @parameter ] + - location: 19 (remaining gas: 1039985.271 units remaining) + [ (Pair "hello" 100) @storage ] + - location: -1 (remaining gas: 1039985.226 units remaining) + [ (Pair "hello" 100) @storage ] + - location: 20 (remaining gas: 1039985.151 units remaining) + [ {} + (Pair "hello" 100) @storage ] + - location: 22 (remaining gas: 1039985.076 units remaining) + [ (Pair {} "hello" 100) ] + - location: -1 (remaining gas: 1039985.031 units remaining) + [ (Pair {} "hello" 100) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{ \"a\" ; \"b\" ; \"c\" }-{ \"a\" ; \"b\" ; \"c\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{ \"a\" ; \"b\" ; \"c\" }-{ \"a\" ; \"b\" ; \"c\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..8a769061c91ae472c2c90455a7a9fbcc3900999c --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{ \"a\" ; \"b\" ; \"c\" }-{ \"a\" ; \"b\" ; \"c\" }].out" @@ -0,0 +1,21 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{ "a" ; "b" ; "c" }-{ "a" ; "b" ; "c" }] + +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039993.748 units remaining) + [ (Pair { "a" ; "b" ; "c" } {}) ] + - location: 9 (remaining gas: 1039993.668 units remaining) + [ { "a" ; "b" ; "c" } @parameter ] + - location: 10 (remaining gas: 1039993.593 units remaining) + [ {} + { "a" ; "b" ; "c" } @parameter ] + - location: 12 (remaining gas: 1039993.518 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: -1 (remaining gas: 1039993.473 units remaining) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{ \"asdf\" ; \"bcde\" }-{ \"asdf\" ; \"bcde\" }].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{ \"asdf\" ; \"bcde\" }-{ \"asdf\" ; \"bcde\" }].out" new file mode 100644 index 0000000000000000000000000000000000000000..4f9cf59057048c88d1827848f93e86b47f6a2b0d --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{ \"asdf\" ; \"bcde\" }-{ \"asdf\" ; \"bcde\" }].out" @@ -0,0 +1,21 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{ "asdf" ; "bcde" }-{ "asdf" ; "bcde" }] + +storage + { "asdf" ; "bcde" } +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039994.151 units remaining) + [ (Pair { "asdf" ; "bcde" } {}) ] + - location: 9 (remaining gas: 1039994.071 units remaining) + [ { "asdf" ; "bcde" } @parameter ] + - location: 10 (remaining gas: 1039993.996 units remaining) + [ {} + { "asdf" ; "bcde" } @parameter ] + - location: 12 (remaining gas: 1039993.921 units remaining) + [ (Pair {} { "asdf" ; "bcde" }) ] + - location: -1 (remaining gas: 1039993.876 units remaining) + [ (Pair {} { "asdf" ; "bcde" }) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{}-{}].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{}-{}].out new file mode 100644 index 0000000000000000000000000000000000000000..6a9d8968d2ec338c34d0ebed0d4f76b250da61b4 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{}-{}].out @@ -0,0 +1,21 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_id.tz-{}-{}-{}] + +storage + {} +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039995.020 units remaining) + [ (Pair {} {}) ] + - location: 9 (remaining gas: 1039994.940 units remaining) + [ {} @parameter ] + - location: 10 (remaining gas: 1039994.865 units remaining) + [ {} + {} @parameter ] + - location: 12 (remaining gas: 1039994.790 units remaining) + [ (Pair {} {}) ] + - location: -1 (remaining gas: 1039994.745 units remaining) + [ (Pair {} {}) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{ -100 ; 1 ; 2 ; 3 }--94].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{ -100 ; 1 ; 2 ; 3 }--94].out new file mode 100644 index 0000000000000000000000000000000000000000..89d9620635e6a04f1e84b83a7298cce3381a2b29 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{ -100 ; 1 ; 2 ; 3 }--94].out @@ -0,0 +1,45 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{ -100 ; 1 ; 2 ; 3 }--94] + +storage + -94 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039990.050 units remaining) + [ (Pair { -100 ; 1 ; 2 ; 3 } 111) ] + - location: 8 (remaining gas: 1039989.970 units remaining) + [ { -100 ; 1 ; 2 ; 3 } @parameter ] + - location: 9 (remaining gas: 1039989.895 units remaining) + [ 0 + { -100 ; 1 ; 2 ; 3 } @parameter ] + - location: 12 (remaining gas: 1039989.825 units remaining) + [ { -100 ; 1 ; 2 ; 3 } @parameter + 0 ] + - location: 15 (remaining gas: 1039989.461 units remaining) + [ -100 ] + - location: 14 (remaining gas: 1039989.416 units remaining) + [ -100 ] + - location: 15 (remaining gas: 1039989.306 units remaining) + [ -99 ] + - location: 14 (remaining gas: 1039989.261 units remaining) + [ -99 ] + - location: 15 (remaining gas: 1039989.151 units remaining) + [ -97 ] + - location: 14 (remaining gas: 1039989.106 units remaining) + [ -97 ] + - location: 15 (remaining gas: 1039988.996 units remaining) + [ -94 ] + - location: 14 (remaining gas: 1039988.951 units remaining) + [ -94 ] + - location: 13 (remaining gas: 1039988.951 units remaining) + [ -94 ] + - location: 16 (remaining gas: 1039988.876 units remaining) + [ {} + -94 ] + - location: 18 (remaining gas: 1039988.801 units remaining) + [ (Pair {} -94) ] + - location: -1 (remaining gas: 1039988.756 units remaining) + [ (Pair {} -94) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{ 1 }-1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{ 1 }-1].out new file mode 100644 index 0000000000000000000000000000000000000000..b47d0ca885021ff22b1cbc0e9b2a4bca60470dff --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{ 1 }-1].out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{ 1 }-1] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039991.460 units remaining) + [ (Pair { 1 } 111) ] + - location: 8 (remaining gas: 1039991.380 units remaining) + [ { 1 } @parameter ] + - location: 9 (remaining gas: 1039991.305 units remaining) + [ 0 + { 1 } @parameter ] + - location: 12 (remaining gas: 1039991.235 units remaining) + [ { 1 } @parameter + 0 ] + - location: 15 (remaining gas: 1039990.979 units remaining) + [ 1 ] + - location: 14 (remaining gas: 1039990.934 units remaining) + [ 1 ] + - location: 13 (remaining gas: 1039990.934 units remaining) + [ 1 ] + - location: 16 (remaining gas: 1039990.859 units remaining) + [ {} + 1 ] + - location: 18 (remaining gas: 1039990.784 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039990.739 units remaining) + [ (Pair {} 1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{}-0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{}-0].out new file mode 100644 index 0000000000000000000000000000000000000000..e2a64aaf7634a3fccaeba04ce0f02f914d233977 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{}-0].out @@ -0,0 +1,29 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_iter.tz-111-{}-0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039991.780 units remaining) + [ (Pair {} 111) ] + - location: 8 (remaining gas: 1039991.700 units remaining) + [ {} @parameter ] + - location: 9 (remaining gas: 1039991.625 units remaining) + [ 0 + {} @parameter ] + - location: 12 (remaining gas: 1039991.555 units remaining) + [ {} @parameter + 0 ] + - location: 13 (remaining gas: 1039991.445 units remaining) + [ 0 ] + - location: 16 (remaining gas: 1039991.370 units remaining) + [ {} + 0 ] + - location: 18 (remaining gas: 1039991.295 units remaining) + [ (Pair {} 0) ] + - location: -1 (remaining gas: 1039991.250 units remaining) + [ (Pair {} 0) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair { \"Hello\" ; \"World\" } None)-\"\"-(Pai.3d2044726e.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair { \"Hello\" ; \"World\" } None)-\"\"-(Pai.3d2044726e.out" new file mode 100644 index 0000000000000000000000000000000000000000..d72a0950e4a8fc6ba07beca641ed087fd7d2dc90 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair { \"Hello\" ; \"World\" } None)-\"\"-(Pai.3d2044726e.out" @@ -0,0 +1,68 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair { "Hello" ; "World" } None)-""-(Pair { "Hello" ; "World" } (Some False))] + +storage + (Pair { "Hello" ; "World" } (Some False)) +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039980.147 units remaining) + [ (Pair "" { "Hello" ; "World" } None) ] + - location: 11 (remaining gas: 1039980.067 units remaining) + [ (Pair "" { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) ] + - location: 12 (remaining gas: 1039979.987 units remaining) + [ (Pair "" { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) ] + - location: 13 (remaining gas: 1039979.907 units remaining) + [ "" @parameter + (Pair "" { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) ] + - location: 17 (remaining gas: 1039979.722 units remaining) + [ (Pair { "Hello" ; "World" } None) @storage + (Pair "" { "Hello" ; "World" } None) ] + - location: 18 (remaining gas: 1039979.642 units remaining) + [ { "Hello" ; "World" } + (Pair "" { "Hello" ; "World" } None) ] + - location: -1 (remaining gas: 1039979.597 units remaining) + [ { "Hello" ; "World" } + (Pair "" { "Hello" ; "World" } None) ] + - location: 15 (remaining gas: 1039979.552 units remaining) + [ { "Hello" ; "World" } + (Pair "" { "Hello" ; "World" } None) ] + - location: 14 (remaining gas: 1039979.552 units remaining) + [ "" @parameter + { "Hello" ; "World" } + (Pair "" { "Hello" ; "World" } None) ] + - location: 19 (remaining gas: 1039979.442 units remaining) + [ False + (Pair "" { "Hello" ; "World" } None) ] + - location: 20 (remaining gas: 1039979.367 units remaining) + [ (Some False) + (Pair "" { "Hello" ; "World" } None) ] + - location: 24 (remaining gas: 1039979.182 units remaining) + [ (Pair { "Hello" ; "World" } None) @storage ] + - location: 25 (remaining gas: 1039979.102 units remaining) + [ { "Hello" ; "World" } ] + - location: -1 (remaining gas: 1039979.057 units remaining) + [ { "Hello" ; "World" } ] + - location: 22 (remaining gas: 1039979.012 units remaining) + [ { "Hello" ; "World" } ] + - location: 21 (remaining gas: 1039979.012 units remaining) + [ (Some False) + { "Hello" ; "World" } ] + - location: 26 (remaining gas: 1039978.942 units remaining) + [ { "Hello" ; "World" } + (Some False) ] + - location: 27 (remaining gas: 1039978.867 units remaining) + [ (Pair { "Hello" ; "World" } (Some False)) ] + - location: 28 (remaining gas: 1039978.792 units remaining) + [ {} + (Pair { "Hello" ; "World" } (Some False)) ] + - location: 30 (remaining gas: 1039978.717 units remaining) + [ (Pair {} { "Hello" ; "World" } (Some False)) ] + - location: -1 (remaining gas: 1039978.672 units remaining) + [ (Pair {} { "Hello" ; "World" } (Some False)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair { \"Hi\" } None)-\"Hi\"-(Pair { \"Hi\" } .564beb9251.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair { \"Hi\" } None)-\"Hi\"-(Pair { \"Hi\" } .564beb9251.out" new file mode 100644 index 0000000000000000000000000000000000000000..9ad6058c1cbc056b4dcc3d40761ce6ae35891405 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair { \"Hi\" } None)-\"Hi\"-(Pair { \"Hi\" } .564beb9251.out" @@ -0,0 +1,68 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair { "Hi" } None)-"Hi"-(Pair { "Hi" } (Some True))] + +storage + (Pair { "Hi" } (Some True)) +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039980.662 units remaining) + [ (Pair "Hi" { "Hi" } None) ] + - location: 11 (remaining gas: 1039980.582 units remaining) + [ (Pair "Hi" { "Hi" } None) + (Pair "Hi" { "Hi" } None) ] + - location: 12 (remaining gas: 1039980.502 units remaining) + [ (Pair "Hi" { "Hi" } None) + (Pair "Hi" { "Hi" } None) + (Pair "Hi" { "Hi" } None) ] + - location: 13 (remaining gas: 1039980.422 units remaining) + [ "Hi" @parameter + (Pair "Hi" { "Hi" } None) + (Pair "Hi" { "Hi" } None) ] + - location: 17 (remaining gas: 1039980.237 units remaining) + [ (Pair { "Hi" } None) @storage + (Pair "Hi" { "Hi" } None) ] + - location: 18 (remaining gas: 1039980.157 units remaining) + [ { "Hi" } + (Pair "Hi" { "Hi" } None) ] + - location: -1 (remaining gas: 1039980.112 units remaining) + [ { "Hi" } + (Pair "Hi" { "Hi" } None) ] + - location: 15 (remaining gas: 1039980.067 units remaining) + [ { "Hi" } + (Pair "Hi" { "Hi" } None) ] + - location: 14 (remaining gas: 1039980.067 units remaining) + [ "Hi" @parameter + { "Hi" } + (Pair "Hi" { "Hi" } None) ] + - location: 19 (remaining gas: 1039979.957 units remaining) + [ True + (Pair "Hi" { "Hi" } None) ] + - location: 20 (remaining gas: 1039979.882 units remaining) + [ (Some True) + (Pair "Hi" { "Hi" } None) ] + - location: 24 (remaining gas: 1039979.697 units remaining) + [ (Pair { "Hi" } None) @storage ] + - location: 25 (remaining gas: 1039979.617 units remaining) + [ { "Hi" } ] + - location: -1 (remaining gas: 1039979.572 units remaining) + [ { "Hi" } ] + - location: 22 (remaining gas: 1039979.527 units remaining) + [ { "Hi" } ] + - location: 21 (remaining gas: 1039979.527 units remaining) + [ (Some True) + { "Hi" } ] + - location: 26 (remaining gas: 1039979.457 units remaining) + [ { "Hi" } + (Some True) ] + - location: 27 (remaining gas: 1039979.382 units remaining) + [ (Pair { "Hi" } (Some True)) ] + - location: 28 (remaining gas: 1039979.307 units remaining) + [ {} + (Pair { "Hi" } (Some True)) ] + - location: 30 (remaining gas: 1039979.232 units remaining) + [ (Pair {} { "Hi" } (Some True)) ] + - location: -1 (remaining gas: 1039979.187 units remaining) + [ (Pair {} { "Hi" } (Some True)) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair {} None)-\"Hi\"-(Pair {} (Some False))].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair {} None)-\"Hi\"-(Pair {} (Some False))].out" new file mode 100644 index 0000000000000000000000000000000000000000..39a16c1499b623dbf81479e5e804ed7303ff2efb --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair {} None)-\"Hi\"-(Pair {} (Some False))].out" @@ -0,0 +1,68 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_member.tz-(Pair {} None)-"Hi"-(Pair {} (Some False))] + +storage + (Pair {} (Some False)) +emitted operations + +big_map diff + +trace + - location: 10 (remaining gas: 1039981.016 units remaining) + [ (Pair "Hi" {} None) ] + - location: 11 (remaining gas: 1039980.936 units remaining) + [ (Pair "Hi" {} None) + (Pair "Hi" {} None) ] + - location: 12 (remaining gas: 1039980.856 units remaining) + [ (Pair "Hi" {} None) + (Pair "Hi" {} None) + (Pair "Hi" {} None) ] + - location: 13 (remaining gas: 1039980.776 units remaining) + [ "Hi" @parameter + (Pair "Hi" {} None) + (Pair "Hi" {} None) ] + - location: 17 (remaining gas: 1039980.591 units remaining) + [ (Pair {} None) @storage + (Pair "Hi" {} None) ] + - location: 18 (remaining gas: 1039980.511 units remaining) + [ {} + (Pair "Hi" {} None) ] + - location: -1 (remaining gas: 1039980.466 units remaining) + [ {} + (Pair "Hi" {} None) ] + - location: 15 (remaining gas: 1039980.421 units remaining) + [ {} + (Pair "Hi" {} None) ] + - location: 14 (remaining gas: 1039980.421 units remaining) + [ "Hi" @parameter + {} + (Pair "Hi" {} None) ] + - location: 19 (remaining gas: 1039980.311 units remaining) + [ False + (Pair "Hi" {} None) ] + - location: 20 (remaining gas: 1039980.236 units remaining) + [ (Some False) + (Pair "Hi" {} None) ] + - location: 24 (remaining gas: 1039980.051 units remaining) + [ (Pair {} None) @storage ] + - location: 25 (remaining gas: 1039979.971 units remaining) + [ {} ] + - location: -1 (remaining gas: 1039979.926 units remaining) + [ {} ] + - location: 22 (remaining gas: 1039979.881 units remaining) + [ {} ] + - location: 21 (remaining gas: 1039979.881 units remaining) + [ (Some False) + {} ] + - location: 26 (remaining gas: 1039979.811 units remaining) + [ {} + (Some False) ] + - location: 27 (remaining gas: 1039979.736 units remaining) + [ (Pair {} (Some False)) ] + - location: 28 (remaining gas: 1039979.661 units remaining) + [ {} + (Pair {} (Some False)) ] + - location: 30 (remaining gas: 1039979.586 units remaining) + [ (Pair {} {} (Some False)) ] + - location: -1 (remaining gas: 1039979.541 units remaining) + [ (Pair {} {} (Some False)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }-6].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }-6].out new file mode 100644 index 0000000000000000000000000000000000000000..27c3e14e1c17d42f50c59f655627065aac7a6227 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }-6].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }-6] + +storage + 6 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039991.900 units remaining) + [ (Pair { 1 ; 2 ; 3 ; 4 ; 5 ; 6 } 111) ] + - location: 8 (remaining gas: 1039991.820 units remaining) + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 } @parameter ] + - location: 9 (remaining gas: 1039991.740 units remaining) + [ 6 ] + - location: 10 (remaining gas: 1039991.665 units remaining) + [ {} + 6 ] + - location: 12 (remaining gas: 1039991.590 units remaining) + [ (Pair {} 6) ] + - location: -1 (remaining gas: 1039991.545 units remaining) + [ (Pair {} 6) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 ; 2 ; 3 }-3].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 ; 2 ; 3 }-3].out new file mode 100644 index 0000000000000000000000000000000000000000..4b87385047e4e6af53a148fec5ea3671df72319f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 ; 2 ; 3 }-3].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 ; 2 ; 3 }-3] + +storage + 3 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.310 units remaining) + [ (Pair { 1 ; 2 ; 3 } 111) ] + - location: 8 (remaining gas: 1039993.230 units remaining) + [ { 1 ; 2 ; 3 } @parameter ] + - location: 9 (remaining gas: 1039993.150 units remaining) + [ 3 ] + - location: 10 (remaining gas: 1039993.075 units remaining) + [ {} + 3 ] + - location: 12 (remaining gas: 1039993 units remaining) + [ (Pair {} 3) ] + - location: -1 (remaining gas: 1039992.955 units remaining) + [ (Pair {} 3) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 }-1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 }-1].out new file mode 100644 index 0000000000000000000000000000000000000000..d6d54def0d52bc68975a47a63e08a7b7cb4e66a6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 }-1].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_size.tz-111-{ 1 }-1] + +storage + 1 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.250 units remaining) + [ (Pair { 1 } 111) ] + - location: 8 (remaining gas: 1039994.170 units remaining) + [ { 1 } @parameter ] + - location: 9 (remaining gas: 1039994.090 units remaining) + [ 1 ] + - location: 10 (remaining gas: 1039994.015 units remaining) + [ {} + 1 ] + - location: 12 (remaining gas: 1039993.940 units remaining) + [ (Pair {} 1) ] + - location: -1 (remaining gas: 1039993.895 units remaining) + [ (Pair {} 1) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{}-0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{}-0].out new file mode 100644 index 0000000000000000000000000000000000000000..5b73c83063c220bd4d29b70b168875cea5e621b0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[set_size.tz-111-{}-0].out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[set_size.tz-111-{}-0] + +storage + 0 +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.570 units remaining) + [ (Pair {} 111) ] + - location: 8 (remaining gas: 1039994.490 units remaining) + [ {} @parameter ] + - location: 9 (remaining gas: 1039994.410 units remaining) + [ 0 ] + - location: 10 (remaining gas: 1039994.335 units remaining) + [ {} + 0 ] + - location: 12 (remaining gas: 1039994.260 units remaining) + [ (Pair {} 0) ] + - location: -1 (remaining gas: 1039994.215 units remaining) + [ (Pair {} 0) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sha3.tz-None-0x48656c6c6f2c20776f726c6421-(Some 0xf345a.a07ae9dddf.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sha3.tz-None-0x48656c6c6f2c20776f726c6421-(Some 0xf345a.a07ae9dddf.out new file mode 100644 index 0000000000000000000000000000000000000000..578ddda9baf934f833dab2ff4a63a4025b4310c8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sha3.tz-None-0x48656c6c6f2c20776f726c6421-(Some 0xf345a.a07ae9dddf.out @@ -0,0 +1,27 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[sha3.tz-None-0x48656c6c6f2c20776f726c6421-(Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722)] + +storage + (Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722) +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039993.690 units remaining) + [ (Pair 0x48656c6c6f2c20776f726c6421 None) ] + - location: 8 (remaining gas: 1039993.610 units remaining) + [ 0x48656c6c6f2c20776f726c6421 @parameter ] + - location: 9 (remaining gas: 1039991.764 units remaining) + [ 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722 ] + - location: 10 (remaining gas: 1039991.689 units remaining) + [ (Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722) ] + - location: 11 (remaining gas: 1039991.614 units remaining) + [ {} + (Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722) ] + - location: 13 (remaining gas: 1039991.539 units remaining) + [ (Pair {} + (Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722)) ] + - location: -1 (remaining gas: 1039991.494 units remaining) + [ (Pair {} + (Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 0 0))-(Some 0)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 0 0))-(Some 0)].out new file mode 100644 index 0000000000000000000000000000000000000000..775c74303a17372c6af3cedb6774be2f1ca18726 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 0 0))-(Some 0)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 0 0))-(Some 0)] + +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Left (Pair 0 0)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Left (Pair 0 0)) @parameter ] + - location: 17 (remaining gas: 1039988.600 units remaining) + [ 0 + 0 ] + - location: 18 (remaining gas: 1039988.420 units remaining) + [ 0 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 0 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 0) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 0) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 0)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 0)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 0 1))-(Some 0)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 0 1))-(Some 0)].out new file mode 100644 index 0000000000000000000000000000000000000000..de83a73400050a01554aa99f81c90f5195a50105 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 0 1))-(Some 0)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 0 1))-(Some 0)] + +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Left (Pair 0 1)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Left (Pair 0 1)) @parameter ] + - location: 17 (remaining gas: 1039988.600 units remaining) + [ 0 + 1 ] + - location: 18 (remaining gas: 1039988.420 units remaining) + [ 0 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 0 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 0) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 0) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 0)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 0)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 1 2))-(Some 4)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 1 2))-(Some 4)].out new file mode 100644 index 0000000000000000000000000000000000000000..ee1d3e07cdb0a5b7b26285788651406b19ab186b --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 1 2))-(Some 4)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 1 2))-(Some 4)] + +storage + (Some 4) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Left (Pair 1 2)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Left (Pair 1 2)) @parameter ] + - location: 17 (remaining gas: 1039988.600 units remaining) + [ 1 + 2 ] + - location: 18 (remaining gas: 1039988.420 units remaining) + [ 4 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 4 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 4) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 4) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 4)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 4)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 15 2))-(Some 60)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 15 2))-(Some 60)].out new file mode 100644 index 0000000000000000000000000000000000000000..da8aa8e812a2e35d91dcbfd1f4891f904e51678f --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 15 2))-(Some 60)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 15 2))-(Some 60)] + +storage + (Some 60) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Left (Pair 15 2)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Left (Pair 15 2)) @parameter ] + - location: 17 (remaining gas: 1039988.600 units remaining) + [ 15 + 2 ] + - location: 18 (remaining gas: 1039988.420 units remaining) + [ 60 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 60 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 60) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 60) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 60)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 60)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 8 1))-(Some 16)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 8 1))-(Some 16)].out new file mode 100644 index 0000000000000000000000000000000000000000..6aa790222950b8d4f129f48569beeb734fa8673e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 8 1))-(Some 16)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Left (Pair 8 1))-(Some 16)] + +storage + (Some 16) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Left (Pair 8 1)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Left (Pair 8 1)) @parameter ] + - location: 17 (remaining gas: 1039988.600 units remaining) + [ 8 + 1 ] + - location: 18 (remaining gas: 1039988.420 units remaining) + [ 16 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 16 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 16) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 16) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 16)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 16)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 0 0))-(Some 0)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 0 0))-(Some 0)].out new file mode 100644 index 0000000000000000000000000000000000000000..21118f4e8ae1f3de918b4d7e02e03ac5629a0845 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 0 0))-(Some 0)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 0 0))-(Some 0)] + +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Right (Pair 0 0)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Right (Pair 0 0)) @parameter ] + - location: 20 (remaining gas: 1039988.600 units remaining) + [ 0 + 0 ] + - location: 21 (remaining gas: 1039988.420 units remaining) + [ 0 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 0 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 0) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 0) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 0)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 0)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 0 1))-(Some 0)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 0 1))-(Some 0)].out new file mode 100644 index 0000000000000000000000000000000000000000..08b937f124b3659ee05592ffcb37bdac0e9b73a5 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 0 1))-(Some 0)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 0 1))-(Some 0)] + +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Right (Pair 0 1)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Right (Pair 0 1)) @parameter ] + - location: 20 (remaining gas: 1039988.600 units remaining) + [ 0 + 1 ] + - location: 21 (remaining gas: 1039988.420 units remaining) + [ 0 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 0 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 0) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 0) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 0)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 0)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 1 2))-(Some 0)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 1 2))-(Some 0)].out new file mode 100644 index 0000000000000000000000000000000000000000..fab1c6a288b380f6f09fffe92da21ae9212e478d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 1 2))-(Some 0)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 1 2))-(Some 0)] + +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Right (Pair 1 2)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Right (Pair 1 2)) @parameter ] + - location: 20 (remaining gas: 1039988.600 units remaining) + [ 1 + 2 ] + - location: 21 (remaining gas: 1039988.420 units remaining) + [ 0 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 0 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 0) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 0) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 0)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 0)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 15 2))-(Some 3)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 15 2))-(Some 3)].out new file mode 100644 index 0000000000000000000000000000000000000000..4c9d0272c341769636187b31e1610890e427465e --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 15 2))-(Some 3)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 15 2))-(Some 3)] + +storage + (Some 3) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Right (Pair 15 2)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Right (Pair 15 2)) @parameter ] + - location: 20 (remaining gas: 1039988.600 units remaining) + [ 15 + 2 ] + - location: 21 (remaining gas: 1039988.420 units remaining) + [ 3 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 3 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 3) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 3) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 3)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 3)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 8 1))-(Some 4)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 8 1))-(Some 4)].out new file mode 100644 index 0000000000000000000000000000000000000000..284688eafbbc2317cbd818186cfca3026b7001ef --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 8 1))-(Some 4)].out @@ -0,0 +1,30 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[shifts.tz-None-(Right (Pair 8 1))-(Some 4)] + +storage + (Some 4) +emitted operations + +big_map diff + +trace + - location: 13 (remaining gas: 1039988.820 units remaining) + [ (Pair (Right (Pair 8 1)) None) ] + - location: 14 (remaining gas: 1039988.740 units remaining) + [ (Right (Pair 8 1)) @parameter ] + - location: 20 (remaining gas: 1039988.600 units remaining) + [ 8 + 1 ] + - location: 21 (remaining gas: 1039988.420 units remaining) + [ 4 ] + - location: -1 (remaining gas: 1039988.375 units remaining) + [ 4 ] + - location: 22 (remaining gas: 1039988.300 units remaining) + [ (Some 4) ] + - location: 23 (remaining gas: 1039988.225 units remaining) + [ {} + (Some 4) ] + - location: 25 (remaining gas: 1039988.150 units remaining) + [ (Pair {} (Some 4)) ] + - location: -1 (remaining gas: 1039988.105 units remaining) + [ (Pair {} (Some 4)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-None-Pair 0 0-None].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-None-Pair 0 0-None].out new file mode 100644 index 0000000000000000000000000000000000000000..0b7092ad445c91c68d35bab63180df83a97cc61d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-None-Pair 0 0-None].out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice.tz-None-Pair 0 0-None] + +storage + None +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.315 units remaining) + [ (Pair (Pair 0 0) None) ] + - location: 10 (remaining gas: 1039988.235 units remaining) + [ (Pair 0 0) @parameter + None @storage ] + - location: 11 (remaining gas: 1039988.165 units remaining) + [ None @storage + (Pair 0 0) @parameter ] + - location: 15 (remaining gas: 1039988 units remaining) + [ ] + - location: 16 (remaining gas: 1039987.925 units remaining) + [ None ] + - location: -1 (remaining gas: 1039987.880 units remaining) + [ None ] + - location: 12 (remaining gas: 1039987.835 units remaining) + [ None ] + - location: 22 (remaining gas: 1039987.760 units remaining) + [ {} + None ] + - location: 24 (remaining gas: 1039987.685 units remaining) + [ (Pair {} None) ] + - location: -1 (remaining gas: 1039987.640 units remaining) + [ (Pair {} None) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 0 0-(Some \"\")].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 0 0-(Some \"\")].out" new file mode 100644 index 0000000000000000000000000000000000000000..42fb8c88b087dfff3b3cdb9934084d9643869a4e --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 0 0-(Some \"\")].out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice.tz-Some "Foo"-Pair 0 0-(Some "")] + +storage + (Some "") +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.031 units remaining) + [ (Pair (Pair 0 0) (Some "Foo")) ] + - location: 10 (remaining gas: 1039987.951 units remaining) + [ (Pair 0 0) @parameter + (Some "Foo") @storage ] + - location: 11 (remaining gas: 1039987.881 units remaining) + [ (Some "Foo") @storage + (Pair 0 0) @parameter ] + - location: 19 (remaining gas: 1039987.721 units remaining) + [ (Pair 0 0) @parameter + "Foo" @storage.some ] + - location: 20 (remaining gas: 1039987.641 units remaining) + [ 0 + 0 + "Foo" @storage.some ] + - location: 21 (remaining gas: 1039987.531 units remaining) + [ (Some "") @storage.some.slice ] + - location: -1 (remaining gas: 1039987.486 units remaining) + [ (Some "") @storage.some.slice ] + - location: 12 (remaining gas: 1039987.441 units remaining) + [ (Some "") ] + - location: 22 (remaining gas: 1039987.366 units remaining) + [ {} + (Some "") ] + - location: 24 (remaining gas: 1039987.291 units remaining) + [ (Pair {} (Some "")) ] + - location: -1 (remaining gas: 1039987.246 units remaining) + [ (Pair {} (Some "")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 0 10-None].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 0 10-None].out" new file mode 100644 index 0000000000000000000000000000000000000000..4d81d23e50759407d753aeb6d500dfb133d5c38b --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 0 10-None].out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice.tz-Some "Foo"-Pair 0 10-None] + +storage + None +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.031 units remaining) + [ (Pair (Pair 0 10) (Some "Foo")) ] + - location: 10 (remaining gas: 1039987.951 units remaining) + [ (Pair 0 10) @parameter + (Some "Foo") @storage ] + - location: 11 (remaining gas: 1039987.881 units remaining) + [ (Some "Foo") @storage + (Pair 0 10) @parameter ] + - location: 19 (remaining gas: 1039987.721 units remaining) + [ (Pair 0 10) @parameter + "Foo" @storage.some ] + - location: 20 (remaining gas: 1039987.641 units remaining) + [ 0 + 10 + "Foo" @storage.some ] + - location: 21 (remaining gas: 1039987.531 units remaining) + [ None @storage.some.slice ] + - location: -1 (remaining gas: 1039987.486 units remaining) + [ None @storage.some.slice ] + - location: 12 (remaining gas: 1039987.441 units remaining) + [ None ] + - location: 22 (remaining gas: 1039987.366 units remaining) + [ {} + None ] + - location: 24 (remaining gas: 1039987.291 units remaining) + [ (Pair {} None) ] + - location: -1 (remaining gas: 1039987.246 units remaining) + [ (Pair {} None) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 0 2-(Some \"Fo\")].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 0 2-(Some \"Fo\")].out" new file mode 100644 index 0000000000000000000000000000000000000000..2e2fd05f8a9359ec3b434e8a1fe0a185c33fde34 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 0 2-(Some \"Fo\")].out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice.tz-Some "Foo"-Pair 0 2-(Some "Fo")] + +storage + (Some "Fo") +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.031 units remaining) + [ (Pair (Pair 0 2) (Some "Foo")) ] + - location: 10 (remaining gas: 1039987.951 units remaining) + [ (Pair 0 2) @parameter + (Some "Foo") @storage ] + - location: 11 (remaining gas: 1039987.881 units remaining) + [ (Some "Foo") @storage + (Pair 0 2) @parameter ] + - location: 19 (remaining gas: 1039987.721 units remaining) + [ (Pair 0 2) @parameter + "Foo" @storage.some ] + - location: 20 (remaining gas: 1039987.641 units remaining) + [ 0 + 2 + "Foo" @storage.some ] + - location: 21 (remaining gas: 1039987.531 units remaining) + [ (Some "Fo") @storage.some.slice ] + - location: -1 (remaining gas: 1039987.486 units remaining) + [ (Some "Fo") @storage.some.slice ] + - location: 12 (remaining gas: 1039987.441 units remaining) + [ (Some "Fo") ] + - location: 22 (remaining gas: 1039987.366 units remaining) + [ {} + (Some "Fo") ] + - location: 24 (remaining gas: 1039987.291 units remaining) + [ (Pair {} (Some "Fo")) ] + - location: -1 (remaining gas: 1039987.246 units remaining) + [ (Pair {} (Some "Fo")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 1 1-(Some \"o\")].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 1 1-(Some \"o\")].out" new file mode 100644 index 0000000000000000000000000000000000000000..f44d60db8b9999606319a3b4e03b26f4fda613d1 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 1 1-(Some \"o\")].out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice.tz-Some "Foo"-Pair 1 1-(Some "o")] + +storage + (Some "o") +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.031 units remaining) + [ (Pair (Pair 1 1) (Some "Foo")) ] + - location: 10 (remaining gas: 1039987.951 units remaining) + [ (Pair 1 1) @parameter + (Some "Foo") @storage ] + - location: 11 (remaining gas: 1039987.881 units remaining) + [ (Some "Foo") @storage + (Pair 1 1) @parameter ] + - location: 19 (remaining gas: 1039987.721 units remaining) + [ (Pair 1 1) @parameter + "Foo" @storage.some ] + - location: 20 (remaining gas: 1039987.641 units remaining) + [ 1 + 1 + "Foo" @storage.some ] + - location: 21 (remaining gas: 1039987.531 units remaining) + [ (Some "o") @storage.some.slice ] + - location: -1 (remaining gas: 1039987.486 units remaining) + [ (Some "o") @storage.some.slice ] + - location: 12 (remaining gas: 1039987.441 units remaining) + [ (Some "o") ] + - location: 22 (remaining gas: 1039987.366 units remaining) + [ {} + (Some "o") ] + - location: 24 (remaining gas: 1039987.291 units remaining) + [ (Pair {} (Some "o")) ] + - location: -1 (remaining gas: 1039987.246 units remaining) + [ (Pair {} (Some "o")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 1 3-None].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 1 3-None].out" new file mode 100644 index 0000000000000000000000000000000000000000..20462394a922e12b796a125a507c881cecb50ded --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 1 3-None].out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice.tz-Some "Foo"-Pair 1 3-None] + +storage + None +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.031 units remaining) + [ (Pair (Pair 1 3) (Some "Foo")) ] + - location: 10 (remaining gas: 1039987.951 units remaining) + [ (Pair 1 3) @parameter + (Some "Foo") @storage ] + - location: 11 (remaining gas: 1039987.881 units remaining) + [ (Some "Foo") @storage + (Pair 1 3) @parameter ] + - location: 19 (remaining gas: 1039987.721 units remaining) + [ (Pair 1 3) @parameter + "Foo" @storage.some ] + - location: 20 (remaining gas: 1039987.641 units remaining) + [ 1 + 3 + "Foo" @storage.some ] + - location: 21 (remaining gas: 1039987.531 units remaining) + [ None @storage.some.slice ] + - location: -1 (remaining gas: 1039987.486 units remaining) + [ None @storage.some.slice ] + - location: 12 (remaining gas: 1039987.441 units remaining) + [ None ] + - location: 22 (remaining gas: 1039987.366 units remaining) + [ {} + None ] + - location: 24 (remaining gas: 1039987.291 units remaining) + [ (Pair {} None) ] + - location: -1 (remaining gas: 1039987.246 units remaining) + [ (Pair {} None) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 10 5-None].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 10 5-None].out" new file mode 100644 index 0000000000000000000000000000000000000000..900208e0782c8d9e7e7189c1cbd521cbf6344ce9 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some \"Foo\"-Pair 10 5-None].out" @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice.tz-Some "Foo"-Pair 10 5-None] + +storage + None +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.031 units remaining) + [ (Pair (Pair 10 5) (Some "Foo")) ] + - location: 10 (remaining gas: 1039987.951 units remaining) + [ (Pair 10 5) @parameter + (Some "Foo") @storage ] + - location: 11 (remaining gas: 1039987.881 units remaining) + [ (Some "Foo") @storage + (Pair 10 5) @parameter ] + - location: 19 (remaining gas: 1039987.721 units remaining) + [ (Pair 10 5) @parameter + "Foo" @storage.some ] + - location: 20 (remaining gas: 1039987.641 units remaining) + [ 10 + 5 + "Foo" @storage.some ] + - location: 21 (remaining gas: 1039987.531 units remaining) + [ None @storage.some.slice ] + - location: -1 (remaining gas: 1039987.486 units remaining) + [ None @storage.some.slice ] + - location: 12 (remaining gas: 1039987.441 units remaining) + [ None ] + - location: 22 (remaining gas: 1039987.366 units remaining) + [ {} + None ] + - location: 24 (remaining gas: 1039987.291 units remaining) + [ (Pair {} None) ] + - location: -1 (remaining gas: 1039987.246 units remaining) + [ (Pair {} None) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some\"FooFooFooFooFooFooFooFooFooFooFooFooFooFo.c508d67bb0.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some\"FooFooFooFooFooFooFooFooFooFooFooFooFooFo.c508d67bb0.out" new file mode 100644 index 0000000000000000000000000000000000000000..937b810394350532a0875f3e43c6f4cc4ff24c69 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice.tz-Some\"FooFooFooFooFooFooFooFooFooFooFooFooFooFo.c508d67bb0.out" @@ -0,0 +1,39 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice.tz-Some"FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo"-Pair 1 10000-None] + +storage + None +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039928.061 units remaining) + [ (Pair (Pair 1 10000) + (Some "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo")) ] + - location: 10 (remaining gas: 1039927.981 units remaining) + [ (Pair 1 10000) @parameter + (Some "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo") @storage ] + - location: 11 (remaining gas: 1039927.911 units remaining) + [ (Some "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo") @storage + (Pair 1 10000) @parameter ] + - location: 19 (remaining gas: 1039927.751 units remaining) + [ (Pair 1 10000) @parameter + "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo" @storage.some ] + - location: 20 (remaining gas: 1039927.671 units remaining) + [ 1 + 10000 + "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo" @storage.some ] + - location: 21 (remaining gas: 1039927.186 units remaining) + [ None @storage.some.slice ] + - location: -1 (remaining gas: 1039927.141 units remaining) + [ None @storage.some.slice ] + - location: 12 (remaining gas: 1039927.096 units remaining) + [ None ] + - location: 22 (remaining gas: 1039927.021 units remaining) + [ {} + None ] + - location: 24 (remaining gas: 1039926.946 units remaining) + [ (Pair {} None) ] + - location: -1 (remaining gas: 1039926.901 units remaining) + [ (Pair {} None) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-None-Pair 0 1-None].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-None-Pair 0 1-None].out new file mode 100644 index 0000000000000000000000000000000000000000..54a189f5c054f8b04c56abb8197f8aec0f483381 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-None-Pair 0 1-None].out @@ -0,0 +1,33 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice_bytes.tz-None-Pair 0 1-None] + +storage + None +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.315 units remaining) + [ (Pair (Pair 0 1) None) ] + - location: 10 (remaining gas: 1039988.235 units remaining) + [ (Pair 0 1) @parameter + None @storage ] + - location: 11 (remaining gas: 1039988.165 units remaining) + [ None @storage + (Pair 0 1) @parameter ] + - location: 15 (remaining gas: 1039988 units remaining) + [ ] + - location: 16 (remaining gas: 1039987.925 units remaining) + [ None ] + - location: -1 (remaining gas: 1039987.880 units remaining) + [ None ] + - location: 12 (remaining gas: 1039987.835 units remaining) + [ None ] + - location: 22 (remaining gas: 1039987.760 units remaining) + [ {} + None ] + - location: 24 (remaining gas: 1039987.685 units remaining) + [ (Pair {} None) ] + - location: -1 (remaining gas: 1039987.640 units remaining) + [ (Pair {} None) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 0 0-(Some 0x)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 0 0-(Some 0x)].out new file mode 100644 index 0000000000000000000000000000000000000000..3ac12be1c2f7d2d1430c134f7d021f31d9d54794 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 0 0-(Some 0x)].out @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 0 0-(Some 0x)] + +storage + (Some 0x) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.075 units remaining) + [ (Pair (Pair 0 0) (Some 0xaabbcc)) ] + - location: 10 (remaining gas: 1039987.995 units remaining) + [ (Pair 0 0) @parameter + (Some 0xaabbcc) @storage ] + - location: 11 (remaining gas: 1039987.925 units remaining) + [ (Some 0xaabbcc) @storage + (Pair 0 0) @parameter ] + - location: 19 (remaining gas: 1039987.765 units remaining) + [ (Pair 0 0) @parameter + 0xaabbcc @storage.some ] + - location: 20 (remaining gas: 1039987.685 units remaining) + [ 0 + 0 + 0xaabbcc @storage.some ] + - location: 21 (remaining gas: 1039987.575 units remaining) + [ (Some 0x) @storage.some.slice ] + - location: -1 (remaining gas: 1039987.530 units remaining) + [ (Some 0x) @storage.some.slice ] + - location: 12 (remaining gas: 1039987.485 units remaining) + [ (Some 0x) ] + - location: 22 (remaining gas: 1039987.410 units remaining) + [ {} + (Some 0x) ] + - location: 24 (remaining gas: 1039987.335 units remaining) + [ (Pair {} (Some 0x)) ] + - location: -1 (remaining gas: 1039987.290 units remaining) + [ (Pair {} (Some 0x)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 0 1-(Some 0xaa)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 0 1-(Some 0xaa)].out new file mode 100644 index 0000000000000000000000000000000000000000..f5d6c97b4c587c935799d1ab529106d4c43071f7 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 0 1-(Some 0xaa)].out @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 0 1-(Some 0xaa)] + +storage + (Some 0xaa) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.075 units remaining) + [ (Pair (Pair 0 1) (Some 0xaabbcc)) ] + - location: 10 (remaining gas: 1039987.995 units remaining) + [ (Pair 0 1) @parameter + (Some 0xaabbcc) @storage ] + - location: 11 (remaining gas: 1039987.925 units remaining) + [ (Some 0xaabbcc) @storage + (Pair 0 1) @parameter ] + - location: 19 (remaining gas: 1039987.765 units remaining) + [ (Pair 0 1) @parameter + 0xaabbcc @storage.some ] + - location: 20 (remaining gas: 1039987.685 units remaining) + [ 0 + 1 + 0xaabbcc @storage.some ] + - location: 21 (remaining gas: 1039987.575 units remaining) + [ (Some 0xaa) @storage.some.slice ] + - location: -1 (remaining gas: 1039987.530 units remaining) + [ (Some 0xaa) @storage.some.slice ] + - location: 12 (remaining gas: 1039987.485 units remaining) + [ (Some 0xaa) ] + - location: 22 (remaining gas: 1039987.410 units remaining) + [ {} + (Some 0xaa) ] + - location: 24 (remaining gas: 1039987.335 units remaining) + [ (Pair {} (Some 0xaa)) ] + - location: -1 (remaining gas: 1039987.290 units remaining) + [ (Pair {} (Some 0xaa)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 1-(Some 0xbb)0].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 1-(Some 0xbb)0].out new file mode 100644 index 0000000000000000000000000000000000000000..d69351d6507f1203f6b855faed1e51492d58bae0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 1-(Some 0xbb)0].out @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 1-(Some 0xbb)0] + +storage + (Some 0xbb) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.075 units remaining) + [ (Pair (Pair 1 1) (Some 0xaabbcc)) ] + - location: 10 (remaining gas: 1039987.995 units remaining) + [ (Pair 1 1) @parameter + (Some 0xaabbcc) @storage ] + - location: 11 (remaining gas: 1039987.925 units remaining) + [ (Some 0xaabbcc) @storage + (Pair 1 1) @parameter ] + - location: 19 (remaining gas: 1039987.765 units remaining) + [ (Pair 1 1) @parameter + 0xaabbcc @storage.some ] + - location: 20 (remaining gas: 1039987.685 units remaining) + [ 1 + 1 + 0xaabbcc @storage.some ] + - location: 21 (remaining gas: 1039987.575 units remaining) + [ (Some 0xbb) @storage.some.slice ] + - location: -1 (remaining gas: 1039987.530 units remaining) + [ (Some 0xbb) @storage.some.slice ] + - location: 12 (remaining gas: 1039987.485 units remaining) + [ (Some 0xbb) ] + - location: 22 (remaining gas: 1039987.410 units remaining) + [ {} + (Some 0xbb) ] + - location: 24 (remaining gas: 1039987.335 units remaining) + [ (Pair {} (Some 0xbb)) ] + - location: -1 (remaining gas: 1039987.290 units remaining) + [ (Pair {} (Some 0xbb)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 1-(Some 0xbb)1].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 1-(Some 0xbb)1].out new file mode 100644 index 0000000000000000000000000000000000000000..45cfcee9c16c5a3afff7a36a11835d26adb9a1dc --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 1-(Some 0xbb)1].out @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 1-(Some 0xbb)1] + +storage + (Some 0xbb) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.075 units remaining) + [ (Pair (Pair 1 1) (Some 0xaabbcc)) ] + - location: 10 (remaining gas: 1039987.995 units remaining) + [ (Pair 1 1) @parameter + (Some 0xaabbcc) @storage ] + - location: 11 (remaining gas: 1039987.925 units remaining) + [ (Some 0xaabbcc) @storage + (Pair 1 1) @parameter ] + - location: 19 (remaining gas: 1039987.765 units remaining) + [ (Pair 1 1) @parameter + 0xaabbcc @storage.some ] + - location: 20 (remaining gas: 1039987.685 units remaining) + [ 1 + 1 + 0xaabbcc @storage.some ] + - location: 21 (remaining gas: 1039987.575 units remaining) + [ (Some 0xbb) @storage.some.slice ] + - location: -1 (remaining gas: 1039987.530 units remaining) + [ (Some 0xbb) @storage.some.slice ] + - location: 12 (remaining gas: 1039987.485 units remaining) + [ (Some 0xbb) ] + - location: 22 (remaining gas: 1039987.410 units remaining) + [ {} + (Some 0xbb) ] + - location: 24 (remaining gas: 1039987.335 units remaining) + [ (Pair {} (Some 0xbb)) ] + - location: -1 (remaining gas: 1039987.290 units remaining) + [ (Pair {} (Some 0xbb)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 2-(Some 0xbbcc)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 2-(Some 0xbbcc)].out new file mode 100644 index 0000000000000000000000000000000000000000..433b45ca7c1ac8d71ea8e7e626bfcb7f29ca1f45 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 2-(Some 0xbbcc)].out @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 2-(Some 0xbbcc)] + +storage + (Some 0xbbcc) +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.075 units remaining) + [ (Pair (Pair 1 2) (Some 0xaabbcc)) ] + - location: 10 (remaining gas: 1039987.995 units remaining) + [ (Pair 1 2) @parameter + (Some 0xaabbcc) @storage ] + - location: 11 (remaining gas: 1039987.925 units remaining) + [ (Some 0xaabbcc) @storage + (Pair 1 2) @parameter ] + - location: 19 (remaining gas: 1039987.765 units remaining) + [ (Pair 1 2) @parameter + 0xaabbcc @storage.some ] + - location: 20 (remaining gas: 1039987.685 units remaining) + [ 1 + 2 + 0xaabbcc @storage.some ] + - location: 21 (remaining gas: 1039987.575 units remaining) + [ (Some 0xbbcc) @storage.some.slice ] + - location: -1 (remaining gas: 1039987.530 units remaining) + [ (Some 0xbbcc) @storage.some.slice ] + - location: 12 (remaining gas: 1039987.485 units remaining) + [ (Some 0xbbcc) ] + - location: 22 (remaining gas: 1039987.410 units remaining) + [ {} + (Some 0xbbcc) ] + - location: 24 (remaining gas: 1039987.335 units remaining) + [ (Pair {} (Some 0xbbcc)) ] + - location: -1 (remaining gas: 1039987.290 units remaining) + [ (Pair {} (Some 0xbbcc)) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 3-None].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 3-None].out new file mode 100644 index 0000000000000000000000000000000000000000..ee157db16bc645f7cc7ebf8dc74dcac63c15dedf --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 3-None].out @@ -0,0 +1,38 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbcc-Pair 1 3-None] + +storage + None +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.075 units remaining) + [ (Pair (Pair 1 3) (Some 0xaabbcc)) ] + - location: 10 (remaining gas: 1039987.995 units remaining) + [ (Pair 1 3) @parameter + (Some 0xaabbcc) @storage ] + - location: 11 (remaining gas: 1039987.925 units remaining) + [ (Some 0xaabbcc) @storage + (Pair 1 3) @parameter ] + - location: 19 (remaining gas: 1039987.765 units remaining) + [ (Pair 1 3) @parameter + 0xaabbcc @storage.some ] + - location: 20 (remaining gas: 1039987.685 units remaining) + [ 1 + 3 + 0xaabbcc @storage.some ] + - location: 21 (remaining gas: 1039987.575 units remaining) + [ None @storage.some.slice ] + - location: -1 (remaining gas: 1039987.530 units remaining) + [ None @storage.some.slice ] + - location: 12 (remaining gas: 1039987.485 units remaining) + [ None ] + - location: 22 (remaining gas: 1039987.410 units remaining) + [ {} + None ] + - location: 24 (remaining gas: 1039987.335 units remaining) + [ (Pair {} None) ] + - location: -1 (remaining gas: 1039987.290 units remaining) + [ (Pair {} None) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbccaabbccaabbccaabbccaabbccaab.df5895de85.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbccaabbccaabbccaabbccaabbccaab.df5895de85.out new file mode 100644 index 0000000000000000000000000000000000000000..9caf98aa15dfb7c22fc50ecca0aca46e48b07d60 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbccaabbccaabbccaabbccaabbccaab.df5895de85.out @@ -0,0 +1,39 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[slice_bytes.tz-Some 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc-Pair 1 10000-None] + +storage + None +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039988.075 units remaining) + [ (Pair (Pair 1 10000) + (Some 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc)) ] + - location: 10 (remaining gas: 1039987.995 units remaining) + [ (Pair 1 10000) @parameter + (Some 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc) @storage ] + - location: 11 (remaining gas: 1039987.925 units remaining) + [ (Some 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc) @storage + (Pair 1 10000) @parameter ] + - location: 19 (remaining gas: 1039987.765 units remaining) + [ (Pair 1 10000) @parameter + 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc @storage.some ] + - location: 20 (remaining gas: 1039987.685 units remaining) + [ 1 + 10000 + 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc @storage.some ] + - location: 21 (remaining gas: 1039987.200 units remaining) + [ None @storage.some.slice ] + - location: -1 (remaining gas: 1039987.155 units remaining) + [ None @storage.some.slice ] + - location: 12 (remaining gas: 1039987.110 units remaining) + [ None ] + - location: 22 (remaining gas: 1039987.035 units remaining) + [ {} + None ] + - location: 24 (remaining gas: 1039986.960 units remaining) + [ (Pair {} None) ] + - location: -1 (remaining gas: 1039986.915 units remaining) + [ (Pair {} None) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[str_id.tz-None-\"Hello\"-(Some \"Hello\")].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[str_id.tz-None-\"Hello\"-(Some \"Hello\")].out" new file mode 100644 index 0000000000000000000000000000000000000000..f0329f32c2180b8541ab9a542998e0392a49944f --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[str_id.tz-None-\"Hello\"-(Some \"Hello\")].out" @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[str_id.tz-None-"Hello"-(Some "Hello")] + +storage + (Some "Hello") +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.376 units remaining) + [ (Pair "Hello" None) ] + - location: 8 (remaining gas: 1039994.296 units remaining) + [ "Hello" @parameter ] + - location: 9 (remaining gas: 1039994.221 units remaining) + [ (Some "Hello") ] + - location: 10 (remaining gas: 1039994.146 units remaining) + [ {} + (Some "Hello") ] + - location: 12 (remaining gas: 1039994.071 units remaining) + [ (Pair {} (Some "Hello")) ] + - location: -1 (remaining gas: 1039994.026 units remaining) + [ (Pair {} (Some "Hello")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[str_id.tz-None-\"abcd\"-(Some \"abcd\")].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[str_id.tz-None-\"abcd\"-(Some \"abcd\")].out" new file mode 100644 index 0000000000000000000000000000000000000000..08082606307a5e3f232d810c22e6f6a70d92724d --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[str_id.tz-None-\"abcd\"-(Some \"abcd\")].out" @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[str_id.tz-None-"abcd"-(Some "abcd")] + +storage + (Some "abcd") +emitted operations + +big_map diff + +trace + - location: 7 (remaining gas: 1039994.386 units remaining) + [ (Pair "abcd" None) ] + - location: 8 (remaining gas: 1039994.306 units remaining) + [ "abcd" @parameter ] + - location: 9 (remaining gas: 1039994.231 units remaining) + [ (Some "abcd") ] + - location: 10 (remaining gas: 1039994.156 units remaining) + [ {} + (Some "abcd") ] + - location: 12 (remaining gas: 1039994.081 units remaining) + [ (Pair {} (Some "abcd")) ] + - location: -1 (remaining gas: 1039994.036 units remaining) + [ (Pair {} (Some "abcd")) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 -100)-\"1970-01-01T00:03:20Z\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 -100)-\"1970-01-01T00:03:20Z\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..012362e78609de0aa03ae2bbbe4f4fc79ad3a5ca --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 -100)-\"1970-01-01T00:03:20Z\"].out" @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 -100)-"1970-01-01T00:03:20Z"] + +storage + "1970-01-01T00:03:20Z" +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039990.200 units remaining) + [ (Pair (Pair "1970-01-01T00:01:40Z" -100) "1970-01-01T00:01:51Z") ] + - location: 9 (remaining gas: 1039990.120 units remaining) + [ (Pair "1970-01-01T00:01:40Z" -100) @parameter ] + - location: 10 (remaining gas: 1039990.040 units remaining) + [ (Pair "1970-01-01T00:01:40Z" -100) @parameter + (Pair "1970-01-01T00:01:40Z" -100) @parameter ] + - location: 11 (remaining gas: 1039989.960 units remaining) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" -100) @parameter ] + - location: 14 (remaining gas: 1039989.805 units remaining) + [ -100 ] + - location: 13 (remaining gas: 1039989.760 units remaining) + [ -100 ] + - location: 12 (remaining gas: 1039989.760 units remaining) + [ "1970-01-01T00:01:40Z" + -100 ] + - location: 15 (remaining gas: 1039989.650 units remaining) + [ "1970-01-01T00:03:20Z" ] + - location: 16 (remaining gas: 1039989.575 units remaining) + [ {} + "1970-01-01T00:03:20Z" ] + - location: 18 (remaining gas: 1039989.500 units remaining) + [ (Pair {} "1970-01-01T00:03:20Z") ] + - location: -1 (remaining gas: 1039989.455 units remaining) + [ (Pair {} "1970-01-01T00:03:20Z") ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 100)-\"1970-01-01T00:00:00Z\"].out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 100)-\"1970-01-01T00:00:00Z\"].out" new file mode 100644 index 0000000000000000000000000000000000000000..b80a63fef0e188757714ba09bbca78dff82daa00 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 100)-\"1970-01-01T00:00:00Z\"].out" @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 100)-"1970-01-01T00:00:00Z"] + +storage + "1970-01-01T00:00:00Z" +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039990.200 units remaining) + [ (Pair (Pair "1970-01-01T00:01:40Z" 100) "1970-01-01T00:01:51Z") ] + - location: 9 (remaining gas: 1039990.120 units remaining) + [ (Pair "1970-01-01T00:01:40Z" 100) @parameter ] + - location: 10 (remaining gas: 1039990.040 units remaining) + [ (Pair "1970-01-01T00:01:40Z" 100) @parameter + (Pair "1970-01-01T00:01:40Z" 100) @parameter ] + - location: 11 (remaining gas: 1039989.960 units remaining) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" 100) @parameter ] + - location: 14 (remaining gas: 1039989.805 units remaining) + [ 100 ] + - location: 13 (remaining gas: 1039989.760 units remaining) + [ 100 ] + - location: 12 (remaining gas: 1039989.760 units remaining) + [ "1970-01-01T00:01:40Z" + 100 ] + - location: 15 (remaining gas: 1039989.650 units remaining) + [ "1970-01-01T00:00:00Z" ] + - location: 16 (remaining gas: 1039989.575 units remaining) + [ {} + "1970-01-01T00:00:00Z" ] + - location: 18 (remaining gas: 1039989.500 units remaining) + [ (Pair {} "1970-01-01T00:00:00Z") ] + - location: -1 (remaining gas: 1039989.455 units remaining) + [ (Pair {} "1970-01-01T00:00:00Z") ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 200000000000000000.3db82d2c25.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 200000000000000000.3db82d2c25.out new file mode 100644 index 0000000000000000000000000000000000000000..2b52e8f16ac07d807e67e4013a0f3c8ed81d97ae --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 200000000000000000.3db82d2c25.out @@ -0,0 +1,36 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[sub_timestamp_delta.tz-111-(Pair 100 2000000000000000000)--1999999999999999900] + +storage + -1999999999999999900 +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039990.200 units remaining) + [ (Pair (Pair "1970-01-01T00:01:40Z" 2000000000000000000) "1970-01-01T00:01:51Z") ] + - location: 9 (remaining gas: 1039990.120 units remaining) + [ (Pair "1970-01-01T00:01:40Z" 2000000000000000000) @parameter ] + - location: 10 (remaining gas: 1039990.040 units remaining) + [ (Pair "1970-01-01T00:01:40Z" 2000000000000000000) @parameter + (Pair "1970-01-01T00:01:40Z" 2000000000000000000) @parameter ] + - location: 11 (remaining gas: 1039989.960 units remaining) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" 2000000000000000000) @parameter ] + - location: 14 (remaining gas: 1039989.805 units remaining) + [ 2000000000000000000 ] + - location: 13 (remaining gas: 1039989.760 units remaining) + [ 2000000000000000000 ] + - location: 12 (remaining gas: 1039989.760 units remaining) + [ "1970-01-01T00:01:40Z" + 2000000000000000000 ] + - location: 15 (remaining gas: 1039989.650 units remaining) + [ -1999999999999999900 ] + - location: 16 (remaining gas: 1039989.575 units remaining) + [ {} + -1999999999999999900 ] + - location: 18 (remaining gas: 1039989.500 units remaining) + [ (Pair {} -1999999999999999900) ] + - location: -1 (remaining gas: 1039989.455 units remaining) + [ (Pair {} -1999999999999999900) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[tez_add_sub.tz-None-(Pair 2000000 1000000)-(Some (Pair .b461aa042b.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[tez_add_sub.tz-None-(Pair 2000000 1000000)-(Some (Pair .b461aa042b.out new file mode 100644 index 0000000000000000000000000000000000000000..f49b3471c43543aca097c5b19c343ffcbc0c2cec --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[tez_add_sub.tz-None-(Pair 2000000 1000000)-(Some (Pair .b461aa042b.out @@ -0,0 +1,69 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[tez_add_sub.tz-None-(Pair 2000000 1000000)-(Some (Pair 3000000 1000000))] + +storage + (Some (Pair 3000000 1000000)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039981.110 units remaining) + [ (Pair (Pair 2000000 1000000) None) ] + - location: 12 (remaining gas: 1039981.030 units remaining) + [ (Pair 2000000 1000000) @parameter ] + - location: 13 (remaining gas: 1039980.950 units remaining) + [ (Pair 2000000 1000000) @parameter + (Pair 2000000 1000000) @parameter ] + - location: 14 (remaining gas: 1039980.870 units remaining) + [ (Pair 2000000 1000000) @parameter + (Pair 2000000 1000000) @parameter + (Pair 2000000 1000000) @parameter ] + - location: 15 (remaining gas: 1039980.790 units remaining) + [ 2000000 + (Pair 2000000 1000000) @parameter + (Pair 2000000 1000000) @parameter ] + - location: 18 (remaining gas: 1039980.635 units remaining) + [ 1000000 + (Pair 2000000 1000000) @parameter ] + - location: 17 (remaining gas: 1039980.590 units remaining) + [ 1000000 + (Pair 2000000 1000000) @parameter ] + - location: 16 (remaining gas: 1039980.590 units remaining) + [ 2000000 + 1000000 + (Pair 2000000 1000000) @parameter ] + - location: 19 (remaining gas: 1039980.505 units remaining) + [ 3000000 + (Pair 2000000 1000000) @parameter ] + - location: 22 (remaining gas: 1039980.350 units remaining) + [ (Pair 2000000 1000000) @parameter + (Pair 2000000 1000000) @parameter ] + - location: 23 (remaining gas: 1039980.270 units remaining) + [ 2000000 + (Pair 2000000 1000000) @parameter ] + - location: 26 (remaining gas: 1039980.115 units remaining) + [ 1000000 ] + - location: 25 (remaining gas: 1039980.070 units remaining) + [ 1000000 ] + - location: 24 (remaining gas: 1039980.070 units remaining) + [ 2000000 + 1000000 ] + - location: 27 (remaining gas: 1039979.985 units remaining) + [ 1000000 ] + - location: -1 (remaining gas: 1039979.940 units remaining) + [ 1000000 ] + - location: 20 (remaining gas: 1039979.940 units remaining) + [ 3000000 + 1000000 ] + - location: 28 (remaining gas: 1039979.865 units remaining) + [ (Pair 3000000 1000000) ] + - location: 29 (remaining gas: 1039979.790 units remaining) + [ (Some (Pair 3000000 1000000)) ] + - location: 30 (remaining gas: 1039979.715 units remaining) + [ {} + (Some (Pair 3000000 1000000)) ] + - location: 32 (remaining gas: 1039979.640 units remaining) + [ (Pair {} (Some (Pair 3000000 1000000))) ] + - location: -1 (remaining gas: 1039979.595 units remaining) + [ (Pair {} (Some (Pair 3000000 1000000))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[tez_add_sub.tz-None-(Pair 2310000 1010000)-(Some (Pair .1e8cf7679c.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[tez_add_sub.tz-None-(Pair 2310000 1010000)-(Some (Pair .1e8cf7679c.out new file mode 100644 index 0000000000000000000000000000000000000000..f75a324ce0042eb3365097ac126caaf8121ddfc9 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[tez_add_sub.tz-None-(Pair 2310000 1010000)-(Some (Pair .1e8cf7679c.out @@ -0,0 +1,69 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[tez_add_sub.tz-None-(Pair 2310000 1010000)-(Some (Pair 3320000 1300000))] + +storage + (Some (Pair 3320000 1300000)) +emitted operations + +big_map diff + +trace + - location: 11 (remaining gas: 1039981.110 units remaining) + [ (Pair (Pair 2310000 1010000) None) ] + - location: 12 (remaining gas: 1039981.030 units remaining) + [ (Pair 2310000 1010000) @parameter ] + - location: 13 (remaining gas: 1039980.950 units remaining) + [ (Pair 2310000 1010000) @parameter + (Pair 2310000 1010000) @parameter ] + - location: 14 (remaining gas: 1039980.870 units remaining) + [ (Pair 2310000 1010000) @parameter + (Pair 2310000 1010000) @parameter + (Pair 2310000 1010000) @parameter ] + - location: 15 (remaining gas: 1039980.790 units remaining) + [ 2310000 + (Pair 2310000 1010000) @parameter + (Pair 2310000 1010000) @parameter ] + - location: 18 (remaining gas: 1039980.635 units remaining) + [ 1010000 + (Pair 2310000 1010000) @parameter ] + - location: 17 (remaining gas: 1039980.590 units remaining) + [ 1010000 + (Pair 2310000 1010000) @parameter ] + - location: 16 (remaining gas: 1039980.590 units remaining) + [ 2310000 + 1010000 + (Pair 2310000 1010000) @parameter ] + - location: 19 (remaining gas: 1039980.505 units remaining) + [ 3320000 + (Pair 2310000 1010000) @parameter ] + - location: 22 (remaining gas: 1039980.350 units remaining) + [ (Pair 2310000 1010000) @parameter + (Pair 2310000 1010000) @parameter ] + - location: 23 (remaining gas: 1039980.270 units remaining) + [ 2310000 + (Pair 2310000 1010000) @parameter ] + - location: 26 (remaining gas: 1039980.115 units remaining) + [ 1010000 ] + - location: 25 (remaining gas: 1039980.070 units remaining) + [ 1010000 ] + - location: 24 (remaining gas: 1039980.070 units remaining) + [ 2310000 + 1010000 ] + - location: 27 (remaining gas: 1039979.985 units remaining) + [ 1300000 ] + - location: -1 (remaining gas: 1039979.940 units remaining) + [ 1300000 ] + - location: 20 (remaining gas: 1039979.940 units remaining) + [ 3320000 + 1300000 ] + - location: 28 (remaining gas: 1039979.865 units remaining) + [ (Pair 3320000 1300000) ] + - location: 29 (remaining gas: 1039979.790 units remaining) + [ (Some (Pair 3320000 1300000)) ] + - location: 30 (remaining gas: 1039979.715 units remaining) + [ {} + (Some (Pair 3320000 1300000)) ] + - location: 32 (remaining gas: 1039979.640 units remaining) + [ (Pair {} (Some (Pair 3320000 1300000))) ] + - location: -1 (remaining gas: 1039979.595 units remaining) + [ (Pair {} (Some (Pair 3320000 1300000))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[uncomb.tz-0-(Pair 1 4 2)-142].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[uncomb.tz-0-(Pair 1 4 2)-142].out new file mode 100644 index 0000000000000000000000000000000000000000..3c7df2e4f9fcdaab5fb64151ac969bd5bafba4b8 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[uncomb.tz-0-(Pair 1 4 2)-142].out @@ -0,0 +1,52 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[uncomb.tz-0-(Pair 1 4 2)-142] + +storage + 142 +emitted operations + +big_map diff + +trace + - location: 9 (remaining gas: 1039986.880 units remaining) + [ (Pair (Pair 1 4 2) 0) ] + - location: 10 (remaining gas: 1039986.800 units remaining) + [ (Pair 1 4 2) @parameter ] + - location: 11 (remaining gas: 1039986.680 units remaining) + [ 1 + 4 + 2 ] + - location: 13 (remaining gas: 1039986.605 units remaining) + [ 100 + 1 + 4 + 2 ] + - location: 16 (remaining gas: 1039986.489 units remaining) + [ 100 + 4 + 2 ] + - location: 17 (remaining gas: 1039986.419 units remaining) + [ 4 + 100 + 2 ] + - location: 18 (remaining gas: 1039986.344 units remaining) + [ 10 + 4 + 100 + 2 ] + - location: 21 (remaining gas: 1039986.228 units remaining) + [ 40 + 100 + 2 ] + - location: 22 (remaining gas: 1039986.118 units remaining) + [ 140 + 2 ] + - location: 23 (remaining gas: 1039986.008 units remaining) + [ 142 ] + - location: 24 (remaining gas: 1039985.933 units remaining) + [ {} + 142 ] + - location: 26 (remaining gas: 1039985.858 units remaining) + [ (Pair {} 142) ] + - location: -1 (remaining gas: 1039985.813 units remaining) + [ (Pair {} 142) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[unpair.tz-Unit-Unit-Unit].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[unpair.tz-Unit-Unit-Unit].out new file mode 100644 index 0000000000000000000000000000000000000000..a04dded41e5d4190d80fc18a760e3e9b5c3fac58 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[unpair.tz-Unit-Unit-Unit].out @@ -0,0 +1,464 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[unpair.tz-Unit-Unit-Unit] + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 6 (remaining gas: 1039845.320 units remaining) + [ (Pair Unit Unit) ] + - location: 7 (remaining gas: 1039845.245 units remaining) + [ ] + - location: 8 (remaining gas: 1039845.170 units remaining) + [ Unit ] + - location: 9 (remaining gas: 1039845.095 units remaining) + [ Unit + Unit ] + - location: 10 (remaining gas: 1039845.020 units remaining) + [ (Pair Unit Unit) ] + - location: 11 (remaining gas: 1039844.940 units remaining) + [ Unit + Unit ] + - location: 12 (remaining gas: 1039844.802 units remaining) + [ ] + - location: 14 (remaining gas: 1039844.727 units remaining) + [ Unit @b ] + - location: 15 (remaining gas: 1039844.652 units remaining) + [ Unit @a + Unit @b ] + - location: 16 (remaining gas: 1039844.577 units remaining) + [ (Pair Unit Unit) ] + - location: 17 (remaining gas: 1039844.497 units remaining) + [ Unit @c + Unit @d ] + - location: 18 (remaining gas: 1039844.359 units remaining) + [ ] + - location: 20 (remaining gas: 1039844.284 units remaining) + [ Unit @b ] + - location: 21 (remaining gas: 1039844.209 units remaining) + [ Unit @a + Unit @b ] + - location: 22 (remaining gas: 1039844.134 units remaining) + [ (Pair Unit Unit) ] + - location: 23 (remaining gas: 1039844.054 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 24 (remaining gas: 1039843.974 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 25 (remaining gas: 1039843.836 units remaining) + [ (Pair Unit Unit) ] + - location: 27 (remaining gas: 1039843.756 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 28 (remaining gas: 1039843.676 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 29 (remaining gas: 1039843.538 units remaining) + [ (Pair Unit Unit) ] + - location: 31 (remaining gas: 1039843.458 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 32 (remaining gas: 1039843.378 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 33 (remaining gas: 1039843.240 units remaining) + [ (Pair Unit Unit) ] + - location: 35 (remaining gas: 1039843.160 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 36 (remaining gas: 1039843.080 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 37 (remaining gas: 1039842.942 units remaining) + [ (Pair Unit Unit) ] + - location: 39 (remaining gas: 1039842.862 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 40 (remaining gas: 1039842.782 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 41 (remaining gas: 1039842.644 units remaining) + [ (Pair Unit Unit) ] + - location: 43 (remaining gas: 1039842.564 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 44 (remaining gas: 1039842.484 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 45 (remaining gas: 1039842.346 units remaining) + [ (Pair Unit Unit) ] + - location: 47 (remaining gas: 1039842.266 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 48 (remaining gas: 1039842.186 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 49 (remaining gas: 1039842.048 units remaining) + [ (Pair Unit Unit) ] + - location: 51 (remaining gas: 1039841.968 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 52 (remaining gas: 1039841.888 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 53 (remaining gas: 1039841.750 units remaining) + [ (Pair Unit Unit) ] + - location: 55 (remaining gas: 1039841.670 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 56 (remaining gas: 1039841.590 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 57 (remaining gas: 1039841.452 units remaining) + [ (Pair Unit Unit) ] + - location: 59 (remaining gas: 1039841.372 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 60 (remaining gas: 1039841.292 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 61 (remaining gas: 1039841.154 units remaining) + [ (Pair Unit Unit) ] + - location: 63 (remaining gas: 1039841.074 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 64 (remaining gas: 1039840.994 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 65 (remaining gas: 1039840.856 units remaining) + [ (Pair Unit Unit) ] + - location: 67 (remaining gas: 1039840.776 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 68 (remaining gas: 1039840.696 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 69 (remaining gas: 1039840.558 units remaining) + [ (Pair Unit Unit) ] + - location: 71 (remaining gas: 1039840.483 units remaining) + [ ] + - location: 72 (remaining gas: 1039840.408 units remaining) + [ Unit @d ] + - location: 73 (remaining gas: 1039840.333 units remaining) + [ Unit @c + Unit @d ] + - location: 74 (remaining gas: 1039840.258 units remaining) + [ (Pair Unit Unit) ] + - location: 75 (remaining gas: 1039840.178 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 76 (remaining gas: 1039840.098 units remaining) + [ Unit @c + Unit @d + (Pair Unit Unit) ] + - location: 77 (remaining gas: 1039839.960 units remaining) + [ (Pair Unit Unit) ] + - location: 79 (remaining gas: 1039839.880 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 80 (remaining gas: 1039839.800 units remaining) + [ Unit @c + Unit @d + (Pair Unit Unit) ] + - location: 81 (remaining gas: 1039839.662 units remaining) + [ (Pair Unit Unit) ] + - location: 83 (remaining gas: 1039839.582 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 84 (remaining gas: 1039839.502 units remaining) + [ Unit @c + Unit @d + (Pair Unit Unit) ] + - location: 85 (remaining gas: 1039839.364 units remaining) + [ (Pair Unit Unit) ] + - location: 87 (remaining gas: 1039839.284 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 88 (remaining gas: 1039839.204 units remaining) + [ Unit @c + Unit @d + (Pair Unit Unit) ] + - location: 89 (remaining gas: 1039839.066 units remaining) + [ (Pair Unit Unit) ] + - location: 91 (remaining gas: 1039838.986 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 92 (remaining gas: 1039838.906 units remaining) + [ Unit @c + Unit @d + (Pair Unit Unit) ] + - location: 93 (remaining gas: 1039838.768 units remaining) + [ (Pair Unit Unit) ] + - location: 95 (remaining gas: 1039838.688 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 96 (remaining gas: 1039838.608 units remaining) + [ Unit @c + Unit @d + (Pair Unit Unit) ] + - location: 97 (remaining gas: 1039838.470 units remaining) + [ (Pair Unit Unit) ] + - location: 99 (remaining gas: 1039838.390 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 100 (remaining gas: 1039838.310 units remaining) + [ Unit @c + Unit @d + (Pair Unit Unit) ] + - location: 101 (remaining gas: 1039838.172 units remaining) + [ (Pair Unit Unit) ] + - location: 103 (remaining gas: 1039838.092 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 104 (remaining gas: 1039838.012 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 105 (remaining gas: 1039837.874 units remaining) + [ (Pair Unit Unit) ] + - location: 107 (remaining gas: 1039837.794 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 108 (remaining gas: 1039837.714 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 109 (remaining gas: 1039837.576 units remaining) + [ (Pair Unit Unit) ] + - location: 111 (remaining gas: 1039837.496 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 112 (remaining gas: 1039837.416 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 113 (remaining gas: 1039837.278 units remaining) + [ (Pair Unit Unit) ] + - location: 115 (remaining gas: 1039837.198 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 116 (remaining gas: 1039837.118 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 117 (remaining gas: 1039836.980 units remaining) + [ (Pair Unit Unit) ] + - location: 119 (remaining gas: 1039836.900 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 120 (remaining gas: 1039836.820 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 121 (remaining gas: 1039836.682 units remaining) + [ (Pair Unit Unit) ] + - location: 123 (remaining gas: 1039836.607 units remaining) + [ ] + - location: 124 (remaining gas: 1039836.532 units remaining) + [ Unit ] + - location: 125 (remaining gas: 1039836.457 units remaining) + [ Unit + Unit ] + - location: 126 (remaining gas: 1039836.382 units remaining) + [ (Pair Unit Unit) ] + - location: 127 (remaining gas: 1039836.302 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 128 (remaining gas: 1039836.222 units remaining) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 129 (remaining gas: 1039836.084 units remaining) + [ (Pair Unit Unit) ] + - location: 131 (remaining gas: 1039836.004 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 132 (remaining gas: 1039835.924 units remaining) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 133 (remaining gas: 1039835.786 units remaining) + [ (Pair Unit Unit) ] + - location: 135 (remaining gas: 1039835.706 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 136 (remaining gas: 1039835.626 units remaining) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 137 (remaining gas: 1039835.488 units remaining) + [ (Pair Unit Unit) ] + - location: 139 (remaining gas: 1039835.408 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 140 (remaining gas: 1039835.328 units remaining) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 141 (remaining gas: 1039835.190 units remaining) + [ (Pair Unit Unit) ] + - location: 143 (remaining gas: 1039835.110 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 144 (remaining gas: 1039835.030 units remaining) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 145 (remaining gas: 1039834.892 units remaining) + [ (Pair Unit Unit) ] + - location: 147 (remaining gas: 1039834.812 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 148 (remaining gas: 1039834.732 units remaining) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 149 (remaining gas: 1039834.594 units remaining) + [ (Pair Unit Unit) ] + - location: 151 (remaining gas: 1039834.514 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 152 (remaining gas: 1039834.434 units remaining) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 153 (remaining gas: 1039834.296 units remaining) + [ (Pair Unit Unit) ] + - location: 155 (remaining gas: 1039834.216 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 156 (remaining gas: 1039834.136 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 157 (remaining gas: 1039833.998 units remaining) + [ (Pair Unit Unit) ] + - location: 159 (remaining gas: 1039833.918 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 160 (remaining gas: 1039833.838 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 161 (remaining gas: 1039833.700 units remaining) + [ (Pair Unit Unit) ] + - location: 163 (remaining gas: 1039833.620 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 164 (remaining gas: 1039833.540 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 165 (remaining gas: 1039833.402 units remaining) + [ (Pair Unit Unit) ] + - location: 167 (remaining gas: 1039833.322 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 168 (remaining gas: 1039833.242 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 169 (remaining gas: 1039833.104 units remaining) + [ (Pair Unit Unit) ] + - location: 171 (remaining gas: 1039833.024 units remaining) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 172 (remaining gas: 1039832.944 units remaining) + [ Unit @a + Unit @b + (Pair Unit Unit) ] + - location: 173 (remaining gas: 1039832.806 units remaining) + [ (Pair Unit Unit) ] + - location: 175 (remaining gas: 1039832.731 units remaining) + [ ] + - location: 176 (remaining gas: 1039832.656 units remaining) + [ Unit ] + - location: 177 (remaining gas: 1039832.581 units remaining) + [ Unit + Unit ] + - location: 178 (remaining gas: 1039832.506 units remaining) + [ (Pair Unit Unit) @p ] + - location: 179 (remaining gas: 1039832.426 units remaining) + [ (Pair Unit Unit) @p + (Pair Unit Unit) @p ] + - location: 180 (remaining gas: 1039832.346 units remaining) + [ Unit @p.a + Unit @b + (Pair Unit Unit) @p ] + - location: 181 (remaining gas: 1039832.208 units remaining) + [ (Pair Unit Unit) @p ] + - location: 183 (remaining gas: 1039832.128 units remaining) + [ (Pair Unit Unit) @p + (Pair Unit Unit) @p ] + - location: 184 (remaining gas: 1039832.048 units remaining) + [ Unit @a + Unit @p.b + (Pair Unit Unit) @p ] + - location: 185 (remaining gas: 1039831.910 units remaining) + [ (Pair Unit Unit) @p ] + - location: 187 (remaining gas: 1039831.830 units remaining) + [ (Pair Unit Unit) @p + (Pair Unit Unit) @p ] + - location: 188 (remaining gas: 1039831.750 units remaining) + [ Unit @p.a + Unit @p.b + (Pair Unit Unit) @p ] + - location: 189 (remaining gas: 1039831.612 units remaining) + [ (Pair Unit Unit) @p ] + - location: 191 (remaining gas: 1039831.532 units remaining) + [ (Pair Unit Unit) @p + (Pair Unit Unit) @p ] + - location: 192 (remaining gas: 1039831.452 units remaining) + [ Unit @a + Unit @p.b + (Pair Unit Unit) @p ] + - location: 193 (remaining gas: 1039831.314 units remaining) + [ (Pair Unit Unit) @p ] + - location: 195 (remaining gas: 1039831.234 units remaining) + [ (Pair Unit Unit) @p + (Pair Unit Unit) @p ] + - location: 196 (remaining gas: 1039831.154 units remaining) + [ Unit @p.a + Unit @b + (Pair Unit Unit) @p ] + - location: 197 (remaining gas: 1039831.016 units remaining) + [ (Pair Unit Unit) @p ] + - location: 199 (remaining gas: 1039830.941 units remaining) + [ ] + - location: 200 (remaining gas: 1039830.866 units remaining) + [ Unit @b ] + - location: 201 (remaining gas: 1039830.791 units remaining) + [ Unit @a + Unit @b ] + - location: 202 (remaining gas: 1039830.716 units remaining) + [ (Pair Unit Unit) @c ] + - location: 203 (remaining gas: 1039830.636 units remaining) + [ Unit @b + Unit @a ] + - location: 204 (remaining gas: 1039830.498 units remaining) + [ ] + - location: 206 (remaining gas: 1039830.423 units remaining) + [ Unit ] + - location: 207 (remaining gas: 1039830.348 units remaining) + [ {} + Unit ] + - location: 209 (remaining gas: 1039830.273 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039830.228 units remaining) + [ (Pair {} Unit) ] + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[voting_power.tz-(Pair 0 0)-\"edpkuBknW28nW72KG6RoHtYW7p1.b2c677ad7b.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[voting_power.tz-(Pair 0 0)-\"edpkuBknW28nW72KG6RoHtYW7p1.b2c677ad7b.out" new file mode 100644 index 0000000000000000000000000000000000000000..3aaaf34285f2cf291de371d1dcaeef2158a59421 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[voting_power.tz-(Pair 0 0)-\"edpkuBknW28nW72KG6RoHtYW7p1.b2c677ad7b.out" @@ -0,0 +1,34 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[voting_power.tz-(Pair 0 0)-"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"-(Pair 500 2500)] + +storage + (Pair 500 2500) +emitted operations + +big_map diff + +trace + - location: 8 (remaining gas: 1039961.660 units remaining) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" 0 0) ] + - location: 9 (remaining gas: 1039961.580 units remaining) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" @parameter ] + - location: 10 (remaining gas: 1039960.970 units remaining) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 11 (remaining gas: 1039745.532 units remaining) + [ 500 ] + - location: 14 (remaining gas: 1039535.019 units remaining) + [ 2500 ] + - location: 13 (remaining gas: 1039534.974 units remaining) + [ 2500 ] + - location: 12 (remaining gas: 1039534.974 units remaining) + [ 500 + 2500 ] + - location: 15 (remaining gas: 1039534.899 units remaining) + [ (Pair 500 2500) ] + - location: 16 (remaining gas: 1039534.824 units remaining) + [ {} + (Pair 500 2500) ] + - location: 18 (remaining gas: 1039534.749 units remaining) + [ (Pair {} 500 2500) ] + - location: -1 (remaining gas: 1039534.704 units remaining) + [ (Pair {} 500 2500) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair False False)-(Some (Left False))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair False False)-(Some (Left False))].out new file mode 100644 index 0000000000000000000000000000000000000000..acc3b4f2fa1a5d6f67157d1fb40175d14ad8a19c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair False False)-(Some (Left False))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair False False)-(Some (Left False))] + +storage + (Some (Left False)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Left (Pair False False)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Left (Pair False False)) @parameter ] + - location: 19 (remaining gas: 1039985.900 units remaining) + [ False + False ] + - location: 20 (remaining gas: 1039985.820 units remaining) + [ False ] + - location: 21 (remaining gas: 1039985.745 units remaining) + [ (Left False) ] + - location: -1 (remaining gas: 1039985.700 units remaining) + [ (Left False) ] + - location: 28 (remaining gas: 1039985.625 units remaining) + [ (Some (Left False)) ] + - location: 29 (remaining gas: 1039985.550 units remaining) + [ {} + (Some (Left False)) ] + - location: 31 (remaining gas: 1039985.475 units remaining) + [ (Pair {} (Some (Left False))) ] + - location: -1 (remaining gas: 1039985.430 units remaining) + [ (Pair {} (Some (Left False))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair False True)-(Some (Left True))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair False True)-(Some (Left True))].out new file mode 100644 index 0000000000000000000000000000000000000000..3f03158b5c01f2cb4616b001ac431ce0df663d2d --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair False True)-(Some (Left True))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair False True)-(Some (Left True))] + +storage + (Some (Left True)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Left (Pair False True)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Left (Pair False True)) @parameter ] + - location: 19 (remaining gas: 1039985.900 units remaining) + [ False + True ] + - location: 20 (remaining gas: 1039985.820 units remaining) + [ True ] + - location: 21 (remaining gas: 1039985.745 units remaining) + [ (Left True) ] + - location: -1 (remaining gas: 1039985.700 units remaining) + [ (Left True) ] + - location: 28 (remaining gas: 1039985.625 units remaining) + [ (Some (Left True)) ] + - location: 29 (remaining gas: 1039985.550 units remaining) + [ {} + (Some (Left True)) ] + - location: 31 (remaining gas: 1039985.475 units remaining) + [ (Pair {} (Some (Left True))) ] + - location: -1 (remaining gas: 1039985.430 units remaining) + [ (Pair {} (Some (Left True))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair True False)-(Some (Left True))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair True False)-(Some (Left True))].out new file mode 100644 index 0000000000000000000000000000000000000000..0a37ec141ecdbeb102fec44dc767b63864f7d3f0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair True False)-(Some (Left True))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair True False)-(Some (Left True))] + +storage + (Some (Left True)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Left (Pair True False)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Left (Pair True False)) @parameter ] + - location: 19 (remaining gas: 1039985.900 units remaining) + [ True + False ] + - location: 20 (remaining gas: 1039985.820 units remaining) + [ True ] + - location: 21 (remaining gas: 1039985.745 units remaining) + [ (Left True) ] + - location: -1 (remaining gas: 1039985.700 units remaining) + [ (Left True) ] + - location: 28 (remaining gas: 1039985.625 units remaining) + [ (Some (Left True)) ] + - location: 29 (remaining gas: 1039985.550 units remaining) + [ {} + (Some (Left True)) ] + - location: 31 (remaining gas: 1039985.475 units remaining) + [ (Pair {} (Some (Left True))) ] + - location: -1 (remaining gas: 1039985.430 units remaining) + [ (Pair {} (Some (Left True))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair True True)-(Some (Left False))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair True True)-(Some (Left False))].out new file mode 100644 index 0000000000000000000000000000000000000000..60f04bd5c1825069d5415ab169ab9e2598f1e606 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair True True)-(Some (Left False))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Left (Pair True True)-(Some (Left False))] + +storage + (Some (Left False)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Left (Pair True True)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Left (Pair True True)) @parameter ] + - location: 19 (remaining gas: 1039985.900 units remaining) + [ True + True ] + - location: 20 (remaining gas: 1039985.820 units remaining) + [ False ] + - location: 21 (remaining gas: 1039985.745 units remaining) + [ (Left False) ] + - location: -1 (remaining gas: 1039985.700 units remaining) + [ (Left False) ] + - location: 28 (remaining gas: 1039985.625 units remaining) + [ (Some (Left False)) ] + - location: 29 (remaining gas: 1039985.550 units remaining) + [ {} + (Some (Left False)) ] + - location: 31 (remaining gas: 1039985.475 units remaining) + [ (Pair {} (Some (Left False))) ] + - location: -1 (remaining gas: 1039985.430 units remaining) + [ (Pair {} (Some (Left False))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 0 0)-(Some (Right 0))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 0 0)-(Some (Right 0))].out new file mode 100644 index 0000000000000000000000000000000000000000..afc553fac2206edcf9eabfcabf5b9fbb3bb56681 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 0 0)-(Some (Right 0))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 0 0)-(Some (Right 0))] + +storage + (Some (Right 0)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Right (Pair 0 0)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Right (Pair 0 0)) @parameter ] + - location: 24 (remaining gas: 1039985.900 units remaining) + [ 0 + 0 ] + - location: 25 (remaining gas: 1039985.790 units remaining) + [ 0 ] + - location: 26 (remaining gas: 1039985.715 units remaining) + [ (Right 0) ] + - location: -1 (remaining gas: 1039985.670 units remaining) + [ (Right 0) ] + - location: 28 (remaining gas: 1039985.595 units remaining) + [ (Some (Right 0)) ] + - location: 29 (remaining gas: 1039985.520 units remaining) + [ {} + (Some (Right 0)) ] + - location: 31 (remaining gas: 1039985.445 units remaining) + [ (Pair {} (Some (Right 0))) ] + - location: -1 (remaining gas: 1039985.400 units remaining) + [ (Pair {} (Some (Right 0))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 0 1)-(Some (Right 1))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 0 1)-(Some (Right 1))].out new file mode 100644 index 0000000000000000000000000000000000000000..23c944ca3fe78fb6a8876ca5d42b2dcc3113df0c --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 0 1)-(Some (Right 1))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 0 1)-(Some (Right 1))] + +storage + (Some (Right 1)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Right (Pair 0 1)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Right (Pair 0 1)) @parameter ] + - location: 24 (remaining gas: 1039985.900 units remaining) + [ 0 + 1 ] + - location: 25 (remaining gas: 1039985.790 units remaining) + [ 1 ] + - location: 26 (remaining gas: 1039985.715 units remaining) + [ (Right 1) ] + - location: -1 (remaining gas: 1039985.670 units remaining) + [ (Right 1) ] + - location: 28 (remaining gas: 1039985.595 units remaining) + [ (Some (Right 1)) ] + - location: 29 (remaining gas: 1039985.520 units remaining) + [ {} + (Some (Right 1)) ] + - location: 31 (remaining gas: 1039985.445 units remaining) + [ (Pair {} (Some (Right 1))) ] + - location: -1 (remaining gas: 1039985.400 units remaining) + [ (Pair {} (Some (Right 1))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 1 0)-(Some (Right 1))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 1 0)-(Some (Right 1))].out new file mode 100644 index 0000000000000000000000000000000000000000..4f061eb6764826f2d39269dbf162dd34f2ae2f35 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 1 0)-(Some (Right 1))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 1 0)-(Some (Right 1))] + +storage + (Some (Right 1)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Right (Pair 1 0)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Right (Pair 1 0)) @parameter ] + - location: 24 (remaining gas: 1039985.900 units remaining) + [ 1 + 0 ] + - location: 25 (remaining gas: 1039985.790 units remaining) + [ 1 ] + - location: 26 (remaining gas: 1039985.715 units remaining) + [ (Right 1) ] + - location: -1 (remaining gas: 1039985.670 units remaining) + [ (Right 1) ] + - location: 28 (remaining gas: 1039985.595 units remaining) + [ (Some (Right 1)) ] + - location: 29 (remaining gas: 1039985.520 units remaining) + [ {} + (Some (Right 1)) ] + - location: 31 (remaining gas: 1039985.445 units remaining) + [ (Pair {} (Some (Right 1))) ] + - location: -1 (remaining gas: 1039985.400 units remaining) + [ (Pair {} (Some (Right 1))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 1 1)-(Some (Right 0))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 1 1)-(Some (Right 0))].out new file mode 100644 index 0000000000000000000000000000000000000000..9e76d93160f9b815866e7b22189949f3dc6edba1 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 1 1)-(Some (Right 0))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 1 1)-(Some (Right 0))] + +storage + (Some (Right 0)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Right (Pair 1 1)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Right (Pair 1 1)) @parameter ] + - location: 24 (remaining gas: 1039985.900 units remaining) + [ 1 + 1 ] + - location: 25 (remaining gas: 1039985.790 units remaining) + [ 0 ] + - location: 26 (remaining gas: 1039985.715 units remaining) + [ (Right 0) ] + - location: -1 (remaining gas: 1039985.670 units remaining) + [ (Right 0) ] + - location: 28 (remaining gas: 1039985.595 units remaining) + [ (Some (Right 0)) ] + - location: 29 (remaining gas: 1039985.520 units remaining) + [ {} + (Some (Right 0)) ] + - location: 31 (remaining gas: 1039985.445 units remaining) + [ (Pair {} (Some (Right 0))) ] + - location: -1 (remaining gas: 1039985.400 units remaining) + [ (Pair {} (Some (Right 0))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 42 21)-(Some (Right 63))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 42 21)-(Some (Right 63))].out new file mode 100644 index 0000000000000000000000000000000000000000..6df6b905ae925168732ac87b48191f195a91908a --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 42 21)-(Some (Right 63))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 42 21)-(Some (Right 63))] + +storage + (Some (Right 63)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Right (Pair 42 21)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Right (Pair 42 21)) @parameter ] + - location: 24 (remaining gas: 1039985.900 units remaining) + [ 42 + 21 ] + - location: 25 (remaining gas: 1039985.790 units remaining) + [ 63 ] + - location: 26 (remaining gas: 1039985.715 units remaining) + [ (Right 63) ] + - location: -1 (remaining gas: 1039985.670 units remaining) + [ (Right 63) ] + - location: 28 (remaining gas: 1039985.595 units remaining) + [ (Some (Right 63)) ] + - location: 29 (remaining gas: 1039985.520 units remaining) + [ {} + (Some (Right 63)) ] + - location: 31 (remaining gas: 1039985.445 units remaining) + [ (Pair {} (Some (Right 63))) ] + - location: -1 (remaining gas: 1039985.400 units remaining) + [ (Pair {} (Some (Right 63))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 42 63)-(Some (Right 21))].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 42 63)-(Some (Right 21))].out new file mode 100644 index 0000000000000000000000000000000000000000..63ae9e5d1bd29ac0c12bd619a189ec7fd097dad0 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 42 63)-(Some (Right 21))].out @@ -0,0 +1,32 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_contract_input_output[xor.tz-None-Right (Pair 42 63)-(Some (Right 21))] + +storage + (Some (Right 21)) +emitted operations + +big_map diff + +trace + - location: 15 (remaining gas: 1039986.120 units remaining) + [ (Pair (Right (Pair 42 63)) None) ] + - location: 16 (remaining gas: 1039986.040 units remaining) + [ (Right (Pair 42 63)) @parameter ] + - location: 24 (remaining gas: 1039985.900 units remaining) + [ 42 + 63 ] + - location: 25 (remaining gas: 1039985.790 units remaining) + [ 21 ] + - location: 26 (remaining gas: 1039985.715 units remaining) + [ (Right 21) ] + - location: -1 (remaining gas: 1039985.670 units remaining) + [ (Right 21) ] + - location: 28 (remaining gas: 1039985.595 units remaining) + [ (Some (Right 21)) ] + - location: 29 (remaining gas: 1039985.520 units remaining) + [ {} + (Some (Right 21)) ] + - location: 31 (remaining gas: 1039985.445 units remaining) + [ (Pair {} (Some (Right 21))) ] + - location: -1 (remaining gas: 1039985.400 units remaining) + [ (Pair {} (Some (Right 21))) ] + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_hash_consistency_michelson_cli.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_hash_consistency_michelson_cli.out new file mode 100644 index 0000000000000000000000000000000000000000..f51379cdce2195f1e1d4e1d8497ae24303c165ee --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_hash_consistency_michelson_cli.out @@ -0,0 +1,23 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_hash_consistency_michelson_cli + +Raw packed data: 0x0507070080acd2c6a501070700bcc485a30b0022 +Script-expression-ID-Hash: expruenXhGp5JQoHJTGv4DzBR8Zm3HGvea8Q8BaMPywsY2bxrHAEgC +Raw Script-expression-ID-Hash: 0x95a69fcbbf773989333dc9b31e246575812dbea19d25089f83a2aeeea16ab4bc +Ledger Blake2b hash: B5B7PuGGVUrdHUW9Df8wPNJQRuUmx56aH1XVpvbUZvW7 +Raw Sha256 hash: 0x538634a0f81b55f1c946c1207a25c262479566d20bd3d5cd2cdbb2940fc45774 +Raw Sha512 hash: 0x49d5c19c2da4ee74f85225c95625a4b77b94724f4285b436b9d4be27d40491354bdc8e9d8a3d9b2857e5fb59b172605edd02fc4b61ce3cd3f84aa11ed1731ff6 +Gas remaining: 1039980.620 units remaining +storage + 0x95a69fcbbf773989333dc9b31e246575812dbea19d25089f83a2aeeea16ab4bc +emitted operations + +big_map diff + + +storage + 0x95a69fcbbf773989333dc9b31e246575812dbea19d25089f83a2aeeea16ab4bc +emitted operations + +big_map diff + + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair { Elt \"bar\" 5 ; Elt \"foo\" 1 } .480b9afc63.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair { Elt \"bar\" 5 ; Elt \"foo\" 1 } .480b9afc63.out" new file mode 100644 index 0000000000000000000000000000000000000000..dc2f7f7608c122b1cfdc17b6a01b0f4d1333a970 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair { Elt \"bar\" 5 ; Elt \"foo\" 1 } .480b9afc63.out" @@ -0,0 +1,9 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair { Elt "bar" 5 ; Elt "foo" 1 } 6)-15-(Pair { Elt "bar" 20 ; Elt "foo" 16 } 36)] + +storage + (Pair { Elt "bar" 20 ; Elt "foo" 16 } 36) +emitted operations + +big_map diff + + diff --git "a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair { Elt \"foo\" 1 } 1)-10-(Pair { .811573b5a7.out" "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair { Elt \"foo\" 1 } 1)-10-(Pair { .811573b5a7.out" new file mode 100644 index 0000000000000000000000000000000000000000..a0212bc16a81067706e81111b27ff738d00ce036 --- /dev/null +++ "b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair { Elt \"foo\" 1 } 1)-10-(Pair { .811573b5a7.out" @@ -0,0 +1,9 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair { Elt "foo" 1 } 1)-10-(Pair { Elt "foo" 11 } 11)] + +storage + (Pair { Elt "foo" 11 } 11) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair {} 0)-10-(Pair {} 0)].out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair {} 0)-10-(Pair {} 0)].out new file mode 100644 index 0000000000000000000000000000000000000000..4378f4246c158f379c5e8514efaedadf532aacc6 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair {} 0)-10-(Pair {} 0)].out @@ -0,0 +1,9 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_map_map_sideeffect[map_map_sideeffect.tz-(Pair {} 0)-10-(Pair {} 0)] + +storage + (Pair {} 0) +emitted operations + +big_map diff + + diff --git a/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_packunpack.out b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_packunpack.out new file mode 100644 index 0000000000000000000000000000000000000000..d2d58b536b7f5316dd0380c92b1e026b9ed40f66 --- /dev/null +++ b/tests_python/tests_009/_regtest_outputs/test_contract_opcodes.TestContractOpcodes::test_packunpack.out @@ -0,0 +1,114 @@ +tests_009/test_contract_opcodes.py::TestContractOpcodes::test_packunpack + +storage + Unit +emitted operations + +big_map diff + +trace + - location: 14 (remaining gas: 1039974.861 units remaining) + [ (Pair (Pair (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003) + Unit) ] + - location: 15 (remaining gas: 1039974.781 units remaining) + [ (Pair (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003) @parameter ] + - location: 16 (remaining gas: 1039974.701 units remaining) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 19 (remaining gas: 1039974.546 units remaining) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 18 (remaining gas: 1039974.501 units remaining) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 17 (remaining gas: 1039974.501 units remaining) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 20 (remaining gas: 1039947.591 units remaining) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 @packed + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 23 (remaining gas: 1039947.380 units remaining) + [ 0 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 24 (remaining gas: 1039947.305 units remaining) + [ True + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: -1 (remaining gas: 1039947.260 units remaining) + [ True + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 26 (remaining gas: 1039947.160 units remaining) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: -1 (remaining gas: 1039947.115 units remaining) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 31 (remaining gas: 1039782.611 units remaining) + [ (Some (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 })) @unpacked ] + - location: 45 (remaining gas: 1039782.476 units remaining) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) @unpacked.some ] + - location: 39 (remaining gas: 1039782.431 units remaining) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) @unpacked.some ] + - location: 46 (remaining gas: 1039782.356 units remaining) + [ ] + - location: 47 (remaining gas: 1039782.281 units remaining) + [ Unit ] + - location: 48 (remaining gas: 1039782.206 units remaining) + [ {} + Unit ] + - location: 50 (remaining gas: 1039782.131 units remaining) + [ (Pair {} Unit) ] + - location: -1 (remaining gas: 1039782.086 units remaining) + [ (Pair {} Unit) ] + +Runtime error in contract [CONTRACT_HASH]: + 1: parameter (pair (pair (pair string (list int)) (set nat)) bytes) ; + 2: storage unit ; + 3: code { CAR ; UNPAIR ; DIP { DUP } ; + 4: PACK ; ASSERT_CMPEQ ; + 5: UNPACK (pair (pair string (list int)) (set nat)) ; ASSERT_SOME ; DROP ; + 6: UNIT ; NIL operation ; PAIR } + 7: +At line 4 characters 14 to 26, +script reached FAILWITH instruction +with Unit +trace + - location: 14 (remaining gas: 1039974.861 units remaining) + [ (Pair (Pair (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004) + Unit) ] + - location: 15 (remaining gas: 1039974.781 units remaining) + [ (Pair (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004) @parameter ] + - location: 16 (remaining gas: 1039974.701 units remaining) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 19 (remaining gas: 1039974.546 units remaining) + [ 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 18 (remaining gas: 1039974.501 units remaining) + [ 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 17 (remaining gas: 1039974.501 units remaining) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 20 (remaining gas: 1039947.591 units remaining) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 @packed + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 23 (remaining gas: 1039947.380 units remaining) + [ -1 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 24 (remaining gas: 1039947.305 units remaining) + [ False + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: -1 (remaining gas: 1039947.260 units remaining) + [ False + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 29 (remaining gas: 1039947.100 units remaining) + [ Unit + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] +Fatal error: + error running script diff --git a/tests_python/tests_009/conftest.py b/tests_python/tests_009/conftest.py new file mode 100644 index 0000000000000000000000000000000000000000..aa6b37d340717bf44ccf2c0940801093b96c4020 --- /dev/null +++ b/tests_python/tests_009/conftest.py @@ -0,0 +1,285 @@ +"""Hooks and fixtures. + +A fixture defines code to be run before and after a (sequence of) test, +E.g. start and stop a server. The fixture is simply specified as a parameter +in the test function, and the yielded values is then accessible with this +parameter. +""" +import os +import tempfile +from typing import Optional, Iterator, List +import pytest +from pytest_regtest import ( + register_converter_pre, + deregister_converter_pre, + _std_conversion, +) +from launchers.sandbox import Sandbox, SandboxMultiBranch +from tools import constants, paths, utils +from tools.client_regression import ClientRegression +from client.client import Client +from client.client_output import CreateMockupResult + +from . import protocol + + +@pytest.fixture(scope="session", autouse=True) +def sanity_check(request) -> None: + """Sanity checks before running the tests.""" + log_dir = request.config.getoption("--log-dir") + if not (log_dir is None or os.path.isdir(log_dir)): + pytest.exit(f"{log_dir} doesn't exist") + + +@pytest.fixture(scope="session") +def log_dir(request) -> Iterator[str]: + """Retrieve user-provided logging directory on the command line.""" + yield request.config.getoption("--log-dir") + + +@pytest.fixture(scope="session") +def singleprocess(request) -> Iterator[bool]: + """Retrieve user-provided single process mode on the command line.""" + yield request.config.getoption("--singleprocess") + + +@pytest.fixture(scope="class") +def session() -> Iterator[dict]: + """Dictionary to store data between tests.""" + yield {} + + +def pytest_runtest_makereport(item, call) -> None: + # hook for incremental test + # from https://docs.pytest.org/en/latest/example/simple.html + if "incremental" in item.keywords: + if call.excinfo is not None: + parent = item.parent + # TODO can we do without this hack? + parent._previousfailed = item # pylint: disable=protected-access + + +def pytest_runtest_setup(item) -> None: + if "incremental" in item.keywords: + previousfailed = getattr(item.parent, "_previousfailed", None) + if previousfailed is not None: + pytest.xfail("previous test failed (%s)" % previousfailed.name) + + +DEAD_DAEMONS_WARN = ''' +It seems some daemons terminated unexpectedly, or didn't launch properly. +You can investigate daemon logs by running this test using the +`--log-dir=LOG_DIR` option.''' + + +@pytest.fixture(scope="class") +def sandbox(log_dir: Optional[str], singleprocess: bool) -> Iterator[Sandbox]: + """Sandboxed network of nodes. + + Nodes, bakers and endorsers are added/removed dynamically.""" + # log_dir is None if not provided on command-line + # singleprocess is false if not provided on command-line + with Sandbox( + paths.TEZOS_HOME, + constants.IDENTITIES, + log_dir=log_dir, + singleprocess=singleprocess, + ) as sandbox: + yield sandbox + assert sandbox.are_daemons_alive(), DEAD_DAEMONS_WARN + + +@pytest.fixture(scope="class") +def client(sandbox: Sandbox) -> Iterator[Client]: + """One node with protocol alpha. + + Activate protocol alpha one year in the past. This avoids waiting + when baking blocks manually from the client using `bake for` + """ + sandbox.add_node(0, params=constants.NODE_PARAMS) + client = sandbox.client(0) + protocol.activate(client, activate_in_the_past=True) + yield client + + +@pytest.fixture(scope="class") +def client_regtest_bis(sandbox: Sandbox) -> Iterator[Client]: + """One node with protocol alpha, regression test enabled. + + Activate protocol alpha one year in the past. (see fixture client). + """ + + def reg_client_factory( + client_path: str, + admin_client_path: str, + host: Optional[str] = None, + base_dir: Optional[str] = None, + rpc_port: Optional[int] = None, + use_tls: Optional[bool] = None, + endpoint: Optional[str] = 'http://127.0.0.1:8732', + mode: str = None, + disable_disclaimer: bool = True, + ) -> ClientRegression: + client = ClientRegression( + client_path=client_path, + admin_client_path=admin_client_path, + host=host, + base_dir=base_dir, + rpc_port=rpc_port, + use_tls=use_tls, + endpoint=endpoint, + mode=mode, + disable_disclaimer=disable_disclaimer, + ) + return client + + sandbox.add_node( + 1, client_factory=reg_client_factory, params=constants.NODE_PARAMS + ) + client = sandbox.client(1) + protocol.activate(client, activate_in_the_past=True) + yield client + + +@pytest.fixture(scope="function") +def client_regtest( + client_regtest_bis: ClientRegression, regtest +) -> Iterator[Client]: + """The client for one node with protocol alpha, with a function level + regression test fixture.""" + deregister_converter_pre(_std_conversion) + client_regtest_bis.set_regtest(regtest) + register_converter_pre(utils.client_always_output_converter) + yield client_regtest_bis + deregister_converter_pre(utils.client_always_output_converter) + + +@pytest.fixture(scope="function") +def client_regtest_scrubbed( + client_regtest: ClientRegression, +) -> Iterator[Client]: + """One node with protocol alpha, regression test and scrubbing enabled.""" + register_converter_pre(utils.client_output_converter) + yield client_regtest + deregister_converter_pre(utils.client_output_converter) + + +@pytest.fixture(scope="class") +def clients(sandbox: Sandbox, request) -> Iterator[List[Client]]: + """N node with protocol alpha. Parameterized by the number of nodes. + + Number of nodes is specified as a class annotation. + @pytest.mark.parametrize('clients', [N], indirect=True) + + Activate protocol alpha one year in the past. (see fixture client). + """ + assert request.param is not None + num_nodes = request.param + for i in range(num_nodes): + # Large number may increases peers connection time + sandbox.add_node(i, params=constants.NODE_PARAMS) + protocol.activate(sandbox.client(0), activate_in_the_past=True) + clients = sandbox.all_clients() + for client in clients: + proto = protocol.HASH + assert utils.check_protocol(client, proto) + yield clients + + +@pytest.fixture(scope="class") +def sandbox_multibranch(log_dir, request) -> Iterator[SandboxMultiBranch]: + """Multi-branch sandbox fixture. Parameterized by map of branches. + + This fixture is identical to `sandbox` except that each node_id is + mapped to a pair (git revision, protocol version). For instance, + suppose a mapping: + + MAP = { 0: ('zeronet', 'alpha'), 1:('mainnet', '003-PsddFKi3'), + 2: ('alphanet', '003-PsddFKi3' } + + If we annotate the class test as follows. + @pytest.mark.parametrize('sandbox_multibranch', [MAP], indirect=True) + + The executables (node, baker, endorser) + - for node_id 0 will be looked up in `TEZOS_BINARY/zeronet`, + - for node_id 1 will be looked up in `TEZOS_BINARY/mainnet` and so on... + + baker and endorser will use the specified protocol version, according + to the tezos executables naming conventions. + """ + if paths.TEZOS_BINARIES is None: + pytest.skip() + branch_map = request.param + assert branch_map is not None + num_peers = max(branch_map) + 1 + + assert paths.TEZOS_BINARIES is not None # helps `mypy` + with SandboxMultiBranch( + paths.TEZOS_BINARIES, + constants.IDENTITIES, + num_peers=num_peers, + log_dir=log_dir, + branch_map=branch_map, + ) as sandbox: + yield sandbox + # this assertion checks that daemons (baker, endorser, node...) didn't + # fail unexpected. + assert sandbox.are_daemons_alive(), DEAD_DAEMONS_WARN + + +def pytest_collection_modifyitems(config, items): + """Adapted from pytest-fixture-marker: adds the regression marker + to all tests that use the regtest fixture. + """ + # pylint: disable=unused-argument + + for item in items: + if 'regtest' in item.fixturenames: + item.add_marker('regression') + + +def _wrap_path(binary: str) -> str: + res = os.path.join(paths.TEZOS_HOME, binary) + assert os.path.isfile(res), f'{res} is not a file' + return res + + +CLIENT = 'tezos-client' +CLIENT_ADMIN = 'tezos-admin-client' + + +@pytest.fixture(scope="class") +def nodeless_client(): + """ + A client that is suited for being used in tests that do not + require a node + """ + client_path = _wrap_path(CLIENT) + client_admin_path = _wrap_path(CLIENT_ADMIN) + client = Client(client_path, client_admin_path, endpoint=None) + yield client + client.cleanup() + + +@pytest.fixture +def mockup_client(sandbox: Sandbox) -> Iterator[Client]: + """ + Returns a mockup client with its persistent directory created + + This is done in two steps, because we want to create the mockup + with a client that doesn't have "--mode mockup" (as per + the public documentation) but we want to return a + client that has "--mode mockup" and uses the base-dir created + in the first step. + + There is no way around this pattern. If you want to create + a mockup using custom arguments; you MUST do the same + as this method. + """ + with tempfile.TemporaryDirectory(prefix='tezos-client.') as base_dir: + unmanaged_client = sandbox.create_client(base_dir=base_dir) + res = unmanaged_client.create_mockup( + protocol=protocol.HASH + ).create_mockup_result + assert res == CreateMockupResult.OK + yield sandbox.create_client(base_dir=base_dir, mode="mockup") diff --git a/tests_python/tests_009/contract_paths.py b/tests_python/tests_009/contract_paths.py new file mode 100644 index 0000000000000000000000000000000000000000..009aec1e953bef0b89defab9495ff1f85210251d --- /dev/null +++ b/tests_python/tests_009/contract_paths.py @@ -0,0 +1,19 @@ +from os import path +from typing import List +from tools import paths + + +def all_contracts(directories: List[str] = None) -> List[str]: + return paths.all_contracts(CONTRACT_PATH, directories) + + +def all_legacy_contracts() -> List[str]: + return all_contracts(['legacy']) + + +CONTRACT_PATH = path.join(paths.TEZOS_HOME, 'tests_python', 'contracts_009') +MACROS_CONTRACT_PATH = path.join(CONTRACT_PATH, 'macros') +ILLTYPED_CONTRACT_PATH = path.join(CONTRACT_PATH, 'ill_typed') +LEGACY_CONTRACT_PATH = path.join(CONTRACT_PATH, 'legacy') +OPCODES_CONTRACT_PATH = path.join(CONTRACT_PATH, 'opcodes') +MINI_SCENARIOS_CONTRACT_PATH = path.join(CONTRACT_PATH, 'mini_scenarios') diff --git a/tests_python/tests_009/multibranch/test_baker_endorser_mb.py b/tests_python/tests_009/multibranch/test_baker_endorser_mb.py new file mode 100644 index 0000000000000000000000000000000000000000..c9a9e977703eee14dd799af0a7c03c3e176d85c1 --- /dev/null +++ b/tests_python/tests_009/multibranch/test_baker_endorser_mb.py @@ -0,0 +1,158 @@ +r""" +Before running this test, make sure that the environment variable +`TEZOS_BINARIES` is defined, and that it points to a properly +set up directory. The script `scripts/build_branches.py` can be used +to build the binaries. + +Example: + + TEZOS_HOME=~/tezos + TEZOS_BINARIES=~/tmp/tezos_binaries + TEZOS_BUILD=~/tmp/tezos_build + scripts/build_branches.py --clone $TEZOS_HOME --build-dir $TEZOS_BUILD \ + --bin-dir $TEZOS_BINARIES \ + d272059bf474018d0c39f5a6e60634a95f0c44aa \ + 6718e80254d4cb8d7ad86bce8cf3cb692550c6e7 + +Note: the test relies (only) on `TEZOS_BINARIES`. The test will be be skipped +if the environment variable isn't defined. + +TODO this test is a copy and paste from tests/test_baker_endorser.py + we could try to somehow re-use the same code with a different fixture. +""" + + +import itertools +import random +import time +import subprocess +import pytest +from tools import utils, constants +from launchers.sandbox import SandboxMultiBranch + + +random.seed(42) +KEYS = [f'bootstrap{i}' for i in range(1, 6)] +NEXT_KEY = itertools.cycle(KEYS) +NUM_NODES = 5 +NEW_NODES = 5 +REPLACE = False +NUM_CYCLES = 60 +TIME_BETWEEN_CYCLE = 1 +assert NEW_NODES <= NUM_CYCLES + + +def random_op(client): + sender = next(NEXT_KEY) + dest = random.choice([key for key in KEYS if key != sender]) + amount = random.randrange(10000) + return client.transfer(amount, sender, dest) + + +# The executables will be selected from revisions A and B +A = "d272059bf474018d0c39f5a6e60634a95f0c44aa" # MAINNET +B = "6718e80254d4cb8d7ad86bce8cf3cb692550c6e7" # MAINNET SNAPSHOT +# The MAP parameter specifies where the binaries should be looked up +MAP = {i: A if i % 2 == 0 else B for i in range(20)} + + +# A and B use the same protocol but it may not be the case +ALPHA = 'PsddFKi32cMJ2qPjf43Qv5GDWLDPZb3T3bF6fLKiF5HtvHNU7aP' +ALPHA_DAEMON = '003-PsddFKi3' + + +def params(i): + extra = ['--history-mode', 'full'] if i % 2 == 1 else [] + return constants.NODE_PARAMS + extra + + +@pytest.mark.parametrize('sandbox_multibranch', [MAP], indirect=True) +@pytest.mark.baker +@pytest.mark.endorser +@pytest.mark.multinode +@pytest.mark.slow +@pytest.mark.multibranch +@pytest.mark.incremental +class TestAllDaemonsWithOperations: + """Runs two baker and two endorsers, generates random op, and + add (or replace) new nodes dynamically. After a little while, + we kill the bakers and check everyone synchronize to the same head.""" + + def test_setup_network(self, sandbox_multibranch: SandboxMultiBranch): + # Set appropriate time to avoid double-baking + for i in range(NUM_NODES): + sandbox_multibranch.add_node(i, params=params(i)) + parameters = dict(constants.ALPHA_PARAMETERS) + parameters["time_between_blocks"] = ["10", "0"] + sandbox_multibranch.client(0).activate_protocol_json(ALPHA, parameters) + sandbox_multibranch.add_baker(0, 'bootstrap5', proto=ALPHA_DAEMON) + sandbox_multibranch.add_baker(1, 'bootstrap4', proto=ALPHA_DAEMON) + sandbox_multibranch.add_endorser( + 0, account='bootstrap1', endorsement_delay=1, proto=ALPHA_DAEMON + ) + sandbox_multibranch.add_endorser( + 1, account='bootstrap2', endorsement_delay=1, proto=ALPHA_DAEMON + ) + + def test_wait_for_alpha(self, sandbox_multibranch: SandboxMultiBranch): + clients = sandbox_multibranch.all_clients() + for client in clients: + proto = ALPHA + assert utils.check_protocol(client, proto) + + def test_network_gen_operations_and_add_nodes( + self, sandbox_multibranch: SandboxMultiBranch, session: dict + ): + node_add_period = NUM_CYCLES // NEW_NODES + for cycle in range(NUM_CYCLES): + i = random.randrange(NUM_NODES) + client = sandbox_multibranch.client(i) + try: + transfer = random_op(client) + session[f'op{cycle}'] = transfer.operation_hash + except subprocess.CalledProcessError: + # some operations may be invalid, e.g. the client sends + # several operation with the same counter + print('# IGNORED INVALID OPERATION') + + if cycle % node_add_period == 0: + # add node + running_nodes = list(sandbox_multibranch.nodes.keys()) + new_node = max(running_nodes) + 1 + if REPLACE: + running_nodes.remove(0) + running_nodes.remove(1) + sandbox_multibranch.rm_node(random.choice(running_nodes)) + sandbox_multibranch.add_node(new_node, params=params(new_node)) + proto = ALPHA + assert utils.check_protocol( + sandbox_multibranch.client(new_node), proto + ) + time.sleep(TIME_BETWEEN_CYCLE) + + def test_kill_baker(self, sandbox_multibranch: SandboxMultiBranch): + sandbox_multibranch.rm_baker(0, proto=ALPHA_DAEMON) + sandbox_multibranch.rm_baker(1, proto=ALPHA_DAEMON) + + def test_synchronize(self, sandbox_multibranch: SandboxMultiBranch): + utils.synchronize(sandbox_multibranch.all_clients()) + + def test_check_operations(self, sandbox_multibranch: SandboxMultiBranch): + min_level = min( + [client.get_level() for client in sandbox_multibranch.all_clients()] + ) + heads_hash = set() + # check there is exactly one head + for client in sandbox_multibranch.all_clients(): + block_hash = utils.get_block_hash(client, min_level) + heads_hash.add(block_hash) + assert len(heads_hash) == 1 + # TODO check for operations inclusion + + def test_check_logs(self, sandbox_multibranch: SandboxMultiBranch): + if not sandbox_multibranch.log_dir: + pytest.skip() + assert sandbox_multibranch.logs + # TODO check more things in the log! endorsement, baking... + error_pattern = r"Uncaught|registered" + assert utils.check_logs(sandbox_multibranch.logs, error_pattern) diff --git a/tests_python/tests_009/protocol.py b/tests_python/tests_009/protocol.py new file mode 100644 index 0000000000000000000000000000000000000000..0e918679c83b10c5b2040f51abc1dcf2c7128c53 --- /dev/null +++ b/tests_python/tests_009/protocol.py @@ -0,0 +1,17 @@ +from tools import constants, utils + +HASH = constants.FLORENCE +DAEMON = constants.FLORENCE_DAEMON +PARAMETERS = constants.FLORENCE_PARAMETERS + +PREV_HASH = constants.EDO +PREV_DAEMON = constants.EDO_DAEMON +PREV_PARAMETERS = constants.EDO_PARAMETERS + + +def activate( + client, parameters=PARAMETERS, timestamp=None, activate_in_the_past=False +): + utils.activate_protocol( + client, HASH, parameters, timestamp, activate_in_the_past + ) diff --git a/tests_python/tests_009/test_baker_endorser.py b/tests_python/tests_009/test_baker_endorser.py new file mode 100644 index 0000000000000000000000000000000000000000..ee3f476640e2aefeca701b62883bc1632d94d2d5 --- /dev/null +++ b/tests_python/tests_009/test_baker_endorser.py @@ -0,0 +1,117 @@ +import itertools +import random +import time +import subprocess +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox +from . import protocol + +random.seed(42) +KEYS = [f'bootstrap{i}' for i in range(1, 6)] +NEXT_KEY = itertools.cycle(KEYS) +NUM_NODES = 5 +NEW_NODES = 5 +REPLACE = False +NUM_CYCLES = 60 +TIME_BETWEEN_CYCLE = 1 +assert NEW_NODES <= NUM_CYCLES + + +def random_op(client): + sender = next(NEXT_KEY) + dest = random.choice([key for key in KEYS if key != sender]) + amount = random.randrange(10000) + return client.transfer(amount, sender, dest) + + +@pytest.mark.baker +@pytest.mark.endorser +@pytest.mark.multinode +@pytest.mark.slow +@pytest.mark.incremental +class TestAllDaemonsWithOperations: + """Runs two baker and two endorsers, generates random op, and + add (or replace) new nodes dynamically. After a little while, + we kill the bakers and check everyone synchronize to the same head.""" + + def test_setup_network(self, sandbox: Sandbox): + parameters = dict(protocol.PARAMETERS) + # each priority has a delay of 1 sec + parameters["time_between_blocks"] = ["1"] + for i in range(NUM_NODES): + sandbox.add_node(i, params=constants.NODE_PARAMS) + protocol.activate(sandbox.client(0), parameters) + sandbox.add_baker(0, 'bootstrap5', proto=protocol.DAEMON) + sandbox.add_baker(1, 'bootstrap4', proto=protocol.DAEMON) + sandbox.add_endorser( + 0, account='bootstrap1', endorsement_delay=1, proto=protocol.DAEMON + ) + sandbox.add_endorser( + 1, account='bootstrap2', endorsement_delay=1, proto=protocol.DAEMON + ) + + def test_wait_for_protocol(self, sandbox: Sandbox): + clients = sandbox.all_clients() + for client in clients: + proto = protocol.HASH + assert utils.check_protocol(client, proto) + + def test_network_gen_operations_and_add_nodes( + self, sandbox: Sandbox, session + ): + node_add_period = NUM_CYCLES // NEW_NODES + for cycle in range(NUM_CYCLES): + i = random.randrange(NUM_NODES) + client = sandbox.client(i) + try: + transfer = random_op(client) + session[f'op{cycle}'] = transfer.operation_hash + except subprocess.CalledProcessError: + # some operations may be invalid, e.g. the client sends + # several operation with the same counter + print('# IGNORED INVALID OPERATION') + + if cycle % node_add_period == 0: + # add node + running_nodes = list(sandbox.nodes.keys()) + new_node = max(running_nodes) + 1 + if REPLACE: + running_nodes.remove(0) + running_nodes.remove(1) + sandbox.rm_node(random.choice(running_nodes)) + sandbox.add_node(new_node, params=constants.NODE_PARAMS) + proto = protocol.HASH + assert utils.check_protocol(sandbox.client(new_node), proto) + time.sleep(TIME_BETWEEN_CYCLE) + + def test_kill_baker(self, sandbox: Sandbox): + sandbox.rm_baker(0, proto=protocol.DAEMON) + sandbox.rm_baker(1, proto=protocol.DAEMON) + + def test_synchronize(self, sandbox: Sandbox): + utils.synchronize(sandbox.all_clients()) + + def test_progress(self, sandbox: Sandbox): + level = sandbox.client(0).get_level() + assert level >= 5 + + def test_check_operations(self, sandbox: Sandbox): + min_level = min( + [client.get_level() for client in sandbox.all_clients()] + ) + heads_hash = set() + # check there is exactly one head + for client in sandbox.all_clients(): + block_hash = utils.get_block_hash(client, min_level) + heads_hash.add(block_hash) + assert len(heads_hash) == 1 + # TODO check for operations inclusion + + def test_check_logs(self, sandbox: Sandbox): + if not sandbox.log_dir: + pytest.skip() + assert sandbox.logs + # TODO check more things in the log! endorsement, baking... + error_pattern = r"Uncaught|registered" + assert utils.check_logs(sandbox.logs, error_pattern) diff --git a/tests_python/tests_009/test_basic.py b/tests_python/tests_009/test_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..7940ba03b8455150ccafa31f7adfc4f5f4ca11ad --- /dev/null +++ b/tests_python/tests_009/test_basic.py @@ -0,0 +1,500 @@ +from os import path +import pytest +from client.client import Client +from tools.paths import ACCOUNT_PATH +from tools.utils import assert_run_failure +from .contract_paths import CONTRACT_PATH + + +BAKE_ARGS = ['--max-priority', '512', '--minimal-timestamp'] +TRANSFER_ARGS = ['--burn-cap', '0.257'] + + +@pytest.mark.incremental +class TestRawContext: + def test_delegates(self, client: Client): + path = '/chains/main/blocks/head/context/raw/bytes/delegates/?depth=3' + res = client.rpc('get', path) + expected = { + "ed25519": { + "02": {"29": None}, + "a9": {"ce": None}, + "c5": {"5c": None}, + "da": {"c9": None}, + "e7": {"67": None}, + } + } + assert res == expected + + def test_no_service_1(self, client: Client): + path = '/chains/main/blocks/head/context/raw/bytes/non-existent' + with assert_run_failure('No service found at this URL'): + client.rpc('get', path) + + def test_no_service_2(self, client: Client): + path = ( + '/chains/main/blocks/head/context/raw/bytes/' + 'non-existent?depth=-1' + ) + expected = 'Command failed : Extraction depth -1 is invalid' + with assert_run_failure(expected): + client.rpc('get', path) + + def test_no_service_3(self, client: Client): + path = '/chains/main/blocks/head/context/raw/bytes/non-existent?depth=0' + with assert_run_failure('No service found at this URL'): + client.rpc('get', path) + + def test_bake(self, client: Client): + client.bake('bootstrap4', BAKE_ARGS) + + @pytest.mark.parametrize( + "identity, message, expected_signature", + [ + ( + 'bootstrap1', + 'msg1', + 'edsigtz68o4FdbpvycnAMDLaa7hpmmhjDx' + 'hx4Zu3QWHLYJtcY1mVhW9m6CCvsciFXwf1' + 'zLmah8fJP51cqaeaciBPGy5osH11AnR', + ), + ( + 'bootstrap2', + 'msg2', + 'edsigtZqhR5SW6vbRSmqwzfS1KiJZLYLe' + 'FhLcCEw7WxjBDxotVx83M2rLe4Baq52SUT' + 'jxfXhQ5J3TabCwqt78kNpoU8j42GDEk4', + ), + ( + 'bootstrap3', + 'msg3', + 'edsigu2PvAWxVYY3jQFVfBRW2Dg61xZMN' + 'esHiNbwCTmpJSyfcJMW8Ch9WABHqsgHQRB' + 'aSs6zZNHVGXfHSBnGCxT9x2b49L2zpMW', + ), + ( + 'bootstrap4', + 'msg4', + 'edsigu5jieost8eeD3JwVrpPuSnKzLLvR3' + 'aqezLPDTvxC3p41qwBEpxuViKriipxig5' + '2NQmJ7AFXTzhM3xgKM2ZaADcSMYWztuJ', + ), + ], + ) + def test_sign_message(self, client, identity, message, expected_signature): + assert client.sign_message(message, identity) == expected_signature + + @pytest.mark.parametrize( + "identity, message, signature", + [ + ( + 'bootstrap1', + 'msg1', + 'edsigtz68o4FdbpvycnAMDLaa7hpmmhjDx' + 'hx4Zu3QWHLYJtcY1mVhW9m6CCvsciFXwf1' + 'zLmah8fJP51cqaeaciBPGy5osH11AnR', + ), + ( + 'bootstrap2', + 'msg2', + 'edsigtZqhR5SW6vbRSmqwzfS1KiJZLYLe' + 'FhLcCEw7WxjBDxotVx83M2rLe4Baq52SUT' + 'jxfXhQ5J3TabCwqt78kNpoU8j42GDEk4', + ), + ( + 'bootstrap3', + 'msg3', + 'edsigu2PvAWxVYY3jQFVfBRW2Dg61xZMN' + 'esHiNbwCTmpJSyfcJMW8Ch9WABHqsgHQRB' + 'aSs6zZNHVGXfHSBnGCxT9x2b49L2zpMW', + ), + ( + 'bootstrap4', + 'msg4', + 'edsigu5jieost8eeD3JwVrpPuSnKzLLvR3' + 'aqezLPDTvxC3p41qwBEpxuViKriipxig5' + '2NQmJ7AFXTzhM3xgKM2ZaADcSMYWztuJ', + ), + ], + ) + def test_check_message(self, client, identity, message, signature): + assert client.check_message(message, identity, signature) + + @pytest.mark.parametrize( + "identity, message, head_block", + [ + ("bootstrap1", "msg1", False), + ("bootstrap2", "msg2", False), + ("bootstrap3", "msg3", True), + ("bootstrap4", "msg4", True), + ], + ) + def test_fail_inject_signed_arbitrary_ope( + self, client, identity, message, head_block + ): + if head_block: + signature = client.sign_message(message, identity, block="head") + else: + signature = client.sign_message(message, identity) + chain_id = client.rpc('get', '/chains/main/chain_id') + head_hash = client.rpc('get', '/chains/main/blocks/head/hash') + run_json = { + 'operation': { + "branch": head_hash, + "contents": [{"kind": "failing_noop", "arbitrary": message}], + 'signature': signature, + }, + 'chain_id': chain_id, + } + run_operation_path = ( + '/chains/main/blocks/head/helpers/scripts/run_operation' + ) + with assert_run_failure( + 'The failing_noop operation cannot be executed by the protocol' + ): + client.rpc('post', run_operation_path, data=run_json) + + def test_gen_keys(self, client: Client, session): + session['keys'] = ['foo', 'bar', 'boo'] + sigs = [None, 'secp256k1', 'ed25519'] + for key, sig in zip(session['keys'], sigs): + args = [] if sig is None else ['--sig', sig] + client.gen_key(key, args) + + def test_transfers(self, client: Client, session): + client.transfer(1000, 'bootstrap1', session['keys'][0], TRANSFER_ARGS) + client.bake('bootstrap1', BAKE_ARGS) + client.transfer(2000, 'bootstrap1', session['keys'][1], TRANSFER_ARGS) + client.bake('bootstrap1', BAKE_ARGS) + client.transfer(3000, 'bootstrap1', session['keys'][2], TRANSFER_ARGS) + client.bake('bootstrap1', BAKE_ARGS) + + def test_balances(self, client: Client, session): + assert client.get_balance(session['keys'][0]) == 1000 + assert client.get_balance(session['keys'][1]) == 2000 + assert client.get_balance(session['keys'][2]) == 3000 + + def test_transfer_bar_foo(self, client: Client, session): + client.transfer( + 1000, + session['keys'][1], + session['keys'][0], + ['--fee', '0', '--force-low-fee'], + ) + client.bake( + 'bootstrap1', + BAKE_ARGS + + [ + '--minimal-fees', + '0', + '--minimal-nanotez-per-byte', + '0', + '--minimal-nanotez-per-gas-unit', + '0', + ], + ) + + def test_balances_bar_foo(self, client: Client, session): + assert client.get_balance(session['keys'][0]) == 2000 + assert client.get_balance(session['keys'][1]) == 1000 + + def test_transfer_foo_bar(self, client: Client, session): + client.transfer( + 1000, session['keys'][0], session['keys'][1], ['--fee', '0.05'] + ) + client.bake('bootstrap1', BAKE_ARGS) + + def test_balances_foo_bar(self, client: Client, session): + assert client.get_balance(session['keys'][0]) == 999.95 + assert client.get_balance(session['keys'][1]) == 2000 + + def test_transfer_failure(self, client: Client, session): + with pytest.raises(Exception): + client.transfer(999.95, session['keys'][0], session['keys'][1]) + + def test_originate_contract_noop(self, client: Client): + contract = path.join(CONTRACT_PATH, 'opcodes', 'noop.tz') + client.remember('noop', contract) + client.typecheck(contract) + client.originate( + 'noop', 1000, 'bootstrap1', contract, ['--burn-cap', '0.295'] + ) + client.bake('bootstrap1', BAKE_ARGS) + + def test_transfer_to_noop(self, client: Client): + client.transfer(10, 'bootstrap1', 'noop', ['--arg', 'Unit']) + client.bake('bootstrap1', BAKE_ARGS) + + def test_contract_hardlimit(self, client: Client): + contract = path.join(CONTRACT_PATH, 'mini_scenarios', 'hardlimit.tz') + client.originate( + 'hardlimit', + 1000, + 'bootstrap1', + contract, + ['--init', '3', '--burn-cap', '0.341'], + ) + client.bake('bootstrap1', BAKE_ARGS) + client.transfer(10, 'bootstrap1', 'hardlimit', ['--arg', 'Unit']) + client.bake('bootstrap1', BAKE_ARGS) + client.transfer(10, 'bootstrap1', 'hardlimit', ['--arg', 'Unit']) + client.bake('bootstrap1', BAKE_ARGS) + + def test_transfers_bootstraps5_bootstrap1(self, client: Client): + assert client.get_balance('bootstrap5') == 4000000 + client.transfer( + 400000, + 'bootstrap5', + 'bootstrap1', + ['--fee', '0', '--force-low-fee'], + ) + client.bake('bootstrap1', BAKE_ARGS) + client.transfer( + 400000, + 'bootstrap1', + 'bootstrap5', + ['--fee', '0', '--force-low-fee'], + ) + client.bake('bootstrap1', BAKE_ARGS) + assert client.get_balance('bootstrap5') == 4000000 + + def test_activate_accounts(self, client: Client, session): + account = f"{ACCOUNT_PATH}/king_commitment.json" + session['keys'] += ['king', 'queen'] + client.activate_account(session['keys'][3], account) + client.bake('bootstrap1', BAKE_ARGS) + account = f"{ACCOUNT_PATH}/queen_commitment.json" + client.activate_account(session['keys'][4], account) + client.bake('bootstrap1', BAKE_ARGS) + assert client.get_balance(session['keys'][3]) == 23932454.669343 + assert client.get_balance(session['keys'][4]) == 72954577.464032 + + def test_transfer_king_queen(self, client: Client, session): + keys = session['keys'] + client.transfer(10, keys[3], keys[4], TRANSFER_ARGS) + client.bake('bootstrap1', BAKE_ARGS) + + def test_duplicate_alias(self, client: Client): + client.add_address("baz", "foo", force=True) + show_foo = client.show_address("foo", show_secret=True) + assert show_foo.secret_key is not None + + +class TestRememberContract: + @pytest.mark.parametrize( + "contract_name,non_originated_contract_address", + [ + ("test", "KT1BuEZtb68c1Q4yjtckcNjGELqWt56Xyesc"), + ("test-2", "KT1TZCh8fmUbuDqFxetPWC2fsQanAHzLx4W9"), + ], + ) + def test_non_originated_contract_no_forcing_not_saved_before( + self, + client, + contract_name, + non_originated_contract_address, + ): + client.remember_contract(contract_name, non_originated_contract_address) + + # As it is always the same client, the contracts have been saved + # before + @pytest.mark.parametrize( + "contract_name,non_originated_contract_address", + [ + ("test", "KT1BuEZtb68c1Q4yjtckcNjGELqWt56Xyesc"), + ("test-2", "KT1TZCh8fmUbuDqFxetPWC2fsQanAHzLx4W9"), + ], + ) + def test_non_originated_contract_with_forcing_and_saved_before( + self, + client, + contract_name, + non_originated_contract_address, + ): + client.remember_contract( + contract_name, non_originated_contract_address, force=True + ) + + # As it is always the same client, the contracts have been saved + # before + @pytest.mark.parametrize( + "contract_name,non_originated_contract_address", + [ + ("test", "KT1BuEZtb68c1Q4yjtckcNjGELqWt56Xyesc"), + ("test-2", "KT1TZCh8fmUbuDqFxetPWC2fsQanAHzLx4W9"), + ], + ) + def test_non_originated_contract_no_forcing_and_saved_before( + self, + client, + contract_name, + non_originated_contract_address, + ): + expected_error = f"The contract alias {contract_name} already exists" + + with assert_run_failure(expected_error): + client.remember_contract( + contract_name, non_originated_contract_address, force=False + ) + + # Test operation size. + def test_operation_size_originate_byte_contract(self, client: Client): + contract = path.join(CONTRACT_PATH, 'opcodes', 'bytes.tz') + client.remember('bytes', contract) + client.typecheck(contract) + client.originate( + 'bytes', 1000, 'bootstrap1', contract, ['--burn-cap', '0.295'] + ) + client.bake('bootstrap1', BAKE_ARGS) + + # Test that operations under 16KB can be injected in the node. + def test_operation_size_small(self, client: Client): + bytes_arg = "0x" + ("00" * 6 * 1024) # 6 KB of data. + + client.transfer(10, 'bootstrap1', 'bytes', ['--arg', bytes_arg]) + client.bake('bootstrap1', BAKE_ARGS) + + # Test that operations between 16KB and 32KB can be injected in the node. + def test_operation_size_medium(self, client: Client): + bytes_arg = "0x" + ("00" * 24 * 1024) # 24 KB of data. + + client.transfer(10, 'bootstrap1', 'bytes', ['--arg', bytes_arg]) + client.bake('bootstrap1', BAKE_ARGS) + + # Test that operations above 32KB fail to be injected. + def test_operation_size_oversized(self, client: Client): + bytes_arg = "0x" + ("00" * 36 * 1024) # 36 KB of data. + + expected_error = "Oversized operation" + with assert_run_failure(expected_error): + client.transfer(10, 'bootstrap1', 'bytes', ['--arg', bytes_arg]) + + # Test operation size with various data types. + def test_operation_size_originate_munch_contract(self, client: Client): + contract = path.join(CONTRACT_PATH, 'opcodes', 'munch.tz') + client.remember('munch', contract) + client.typecheck(contract) + client.originate( + 'munch', 1000, 'bootstrap1', contract, ['--burn-cap', '0.295'] + ) + client.bake('bootstrap1', BAKE_ARGS) + + # Test that a large operation under 32KB can be injected in the node + # (variant using a lambda with deep nesting). + def test_operation_size_with_lambda_ok(self, client: Client): + # Each pair of braces is encoded on 5 bytes so this takes + # 5 * 6 * 1024 = 30 KB < 32KB + big_arg = ("{" * 6 * 1024) + ("}" * 6 * 1024) + + client.transfer( + 10, + 'bootstrap1', + 'munch', + ['--arg', big_arg, "--entrypoint", "lambda"], + ) + client.bake('bootstrap1', BAKE_ARGS) + + # Test that a large operation over 32KB cannot be injected in the node, + # and the error is not a stack overflow + # (variant using a lambda with deep nesting). + def test_operation_size_with_lambda_fail(self, client: Client): + # Each pair of braces is encoded on 5 bytes so this takes + # 5 * 7 * 1024 = 35 KB > 32KB + big_arg = ("{" * 7 * 1024) + ("}" * 7 * 1024) + + expected_error = "Oversized operation" + with assert_run_failure(expected_error): + client.transfer( + 10, + 'bootstrap1', + 'munch', + ['--arg', big_arg, "--entrypoint", "lambda"], + ) + + # Test that a large operation under 32KB can be injected in the node + # (variant using a long list). + def test_operation_size_with_list_ok(self, client: Client): + # Each element in the list takes 2 bytes so about 30KB in total + big_arg = "{" + ("0; " * 15 * 1024) + "}" + + client.transfer( + 10, + 'bootstrap1', + 'munch', + ['--arg', big_arg, "--entrypoint", "list_nat"], + ) + client.bake('bootstrap1', BAKE_ARGS) + + def test_operation_size_with_list_syntax_error(self, client: Client): + # Each element in the list takes 2 bytes so about 30KB in total + big_arg = "{" + ("0; " * 15 * 1024) + "'foo;'" + "}" + + expected_error = "transfer simulation failed" + with assert_run_failure(expected_error): + client.transfer( + 10, + 'bootstrap1', + 'munch', + ['--arg', big_arg, "--entrypoint", "list_nat"], + ) + + def test_operation_size_with_list_ill_typed(self, client: Client): + # Each element in the list takes 2 bytes so about 30KB in total + big_arg = "{" + ("0; " * 15 * 1024) + "Unit;" + "}" + + expected_error = "transfer simulation failed" + with assert_run_failure(expected_error): + client.transfer( + 10, + 'bootstrap1', + 'munch', + ['--arg', big_arg, "--entrypoint", "list_nat"], + ) + + # Test that a large operation over 32KB cannot be injected in the node, + # and the error is not a stack overflow + # (variant using a long list). + def test_operation_size_with_list_fail(self, client: Client): + # Each element in the list takes 2 bytes so about 34KB in total + big_arg = "{" + ("0; " * 17 * 1024) + "}" + + expected_error = "Oversized operation" + with assert_run_failure(expected_error): + client.transfer( + 10, + 'bootstrap1', + 'munch', + ['--arg', big_arg, "--entrypoint", "list_nat"], + ) + + # Test that a large operation under 32KB can be injected in the node + # (variant using a big nat). + def test_operation_size_with_nat_ok(self, client: Client): + # The encoding for nat uses a byte to encode 7 bits of the number + # so the size of 2 ** (7 * n) is about n bytes + big_arg = 2 ** (7 * 30 * 1024) + + client.transfer( + 10, + 'bootstrap1', + 'munch', + ['--arg', f"{big_arg}", "--entrypoint", "nat"], + ) + client.bake('bootstrap1', BAKE_ARGS) + + # Test that a large operation over 32KB cannot be injected in the node, + # and the error is not a stack overflow + # (variant using a big nat). + def test_operation_size_with_nat_fail(self, client: Client): + # The encoding for nat uses a byte to encode 7 bits of the number + # so the size of 2 ** (7 * n) is about n bytes + big_arg = 2 ** (7 * 33 * 1024) + + expected_error = "Oversized operation" + with assert_run_failure(expected_error): + client.transfer( + 10, + 'bootstrap1', + 'munch', + ['--arg', f"{big_arg}", "--entrypoint", "nat"], + ) diff --git a/tests_python/tests_009/test_binaries.py b/tests_python/tests_009/test_binaries.py new file mode 100644 index 0000000000000000000000000000000000000000..b401b4b8cb392485cfa76c1e8b24b440173ff10e --- /dev/null +++ b/tests_python/tests_009/test_binaries.py @@ -0,0 +1,48 @@ +""" +Tests common utility functionality of binaries shipped with Tezos. +""" + +import subprocess +from typing import List + +from process import process_utils +from tools import paths +from . import protocol + + +PROTO_BINARIES = [ + binary + "-" + protocol.DAEMON + for binary in ["tezos-baker", "tezos-endorser", "tezos-accuser"] +] + +BINARIES = [ + "tezos-codec", + "tezos-client", + "tezos-admin-client", + "tezos-protocol-compiler", + "tezos-node", + "tezos-snoop", + "tezos-validator", +] + PROTO_BINARIES + + +def run_cmd(cmd: List[str]) -> str: + """Pretty print a command. Execute it, print and return its standard + output.""" + print(process_utils.format_command(cmd)) + process_ret = subprocess.run( + cmd, check=True, capture_output=True, text=True + ) + print(process_ret.stdout) + return process_ret.stdout.strip() + + +class TestBinaries: + def test_version(self): + """Tests that all binaries accept the --version flag and that the + report the same version""" + versions = set() + for binary in BINARIES: + version = run_cmd([paths.TEZOS_HOME + binary, "--version"]) + versions.add(version) + assert len(versions) == 1, "All binaries should report the same version" diff --git a/tests_python/tests_009/test_block_times_ideal_scenario.py b/tests_python/tests_009/test_block_times_ideal_scenario.py new file mode 100644 index 0000000000000000000000000000000000000000..668237aa05fb951897cecbfcc96cffa37cfdb117 --- /dev/null +++ b/tests_python/tests_009/test_block_times_ideal_scenario.py @@ -0,0 +1,140 @@ +import random +import time +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox +from . import protocol + +random.seed(42) +NUM_NODES = 5 +TEST_DURATION = 10 +BD = 3 # base delay = time_between_blocks[0] +PD = 20 # priority delay = time_between_blocks[1] +IE = 2 # initial_endorsers + + +@pytest.mark.baker +@pytest.mark.multinode +@pytest.mark.slow +@pytest.mark.incremental +class TestBakers: + """Run NUM_NODES bakers and check that blocks are produced with the + expected timestamp. + + """ + + def test_setup_network(self, sandbox: Sandbox): + parameters = dict(protocol.PARAMETERS) + + parameters["time_between_blocks"] = [str(BD), str(PD)] + parameters["initial_endorsers"] = IE + for i in range(NUM_NODES): + sandbox.add_node(i, params=constants.NODE_PARAMS) + + protocol.activate(sandbox.client(0), parameters) + + def test_wait_for_protocol(self, sandbox: Sandbox): + clients = sandbox.all_clients() + for client in clients: + proto = protocol.HASH + assert utils.check_protocol(client, proto) + assert client.get_level() == 1 + + def test_add_bakers(self, sandbox: Sandbox): + for i in range(NUM_NODES): + sandbox.add_baker(i, f'bootstrap{i+1}', proto=protocol.DAEMON) + + def test_check_level_and_timestamp(self, sandbox: Sandbox): + time.sleep(TEST_DURATION) + min_level = min( + [client.get_level() for client in sandbox.all_clients()] + ) + heads_hash = set() + # check there is exactly one block at the common level + for client in sandbox.all_clients(): + header = client.get_header(block=str(min_level)) + heads_hash.add(header['hash']) + assert len(heads_hash) == 1 + + # at least two new blocks should have been produced + assert min_level >= 3 + + # check that the timestamp difference is the expected one, + # use blocks at levels 2 and 3 (and not 1 and 2) because the + # one at level 2 may be baked late if the bakers start slowly + client = sandbox.client(0) + ts1 = client.get_block_timestamp(block=str(2)) + ts2 = client.get_block_timestamp(block=str(3)) + time_diff = (ts2 - ts1).total_seconds() + # there will be initial_endorsers missing endorsements + # so the block delay is BD + IE * 1 + assert protocol.PARAMETERS["delay_per_missing_endorsement"] == '1' + assert time_diff == BD + IE + + +@pytest.mark.baker +@pytest.mark.endorser +@pytest.mark.multinode +@pytest.mark.slow +@pytest.mark.incremental +class TestBakersAndEndorsers: + """Run NUM_NODES bakers and endorsers and check that blocks are + produced with the expected timestamp.""" + + def test_setup_network(self, sandbox: Sandbox): + parameters = dict(protocol.PARAMETERS) + parameters["time_between_blocks"] = [str(BD), str(PD)] + # we require all endorsements to be present + parameters["initial_endorsers"] = parameters["endorsers_per_block"] + for i in range(NUM_NODES): + sandbox.add_node(i, params=constants.NODE_PARAMS) + + protocol.activate(sandbox.client(0), parameters) + + def test_wait_for_protocol(self, sandbox: Sandbox): + clients = sandbox.all_clients() + for client in clients: + proto = protocol.HASH + assert utils.check_protocol(client, proto) + assert client.get_level() == 1 + + def test_add_bakers_and_endorsers(self, sandbox: Sandbox): + for i in range(NUM_NODES): + sandbox.add_baker(i, f'bootstrap{i+1}', proto=protocol.DAEMON) + for i in range(NUM_NODES): + sandbox.add_endorser( + i, + account=f'bootstrap{i+1}', + endorsement_delay=0, + proto=protocol.DAEMON, + ) + + def test_check_level_and_timestamp(self, sandbox: Sandbox): + client = sandbox.client(0) + first_level = client.get_level() + time.sleep(TEST_DURATION) + levels = [client.get_level() for client in sandbox.all_clients()] + min_level = min(levels) + max_level = max(levels) + + heads_hash = set() + # check there is exactly one block at the common level + for client in sandbox.all_clients(): + header = client.get_header(block=str(min_level)) + heads_hash.add(header['hash']) + assert len(heads_hash) == 1 + + # there should be one block every two seconds, so normally the max level + # should have increased with TEST_DURATION / BD levels + # we decrement by 1 "for safety" + assert max_level >= first_level - 1 + TEST_DURATION / BD + + # the rpc calls should be quick wrt to the time between blocks, + # so nodes do not have time to diverge + assert min_level >= max_level - 1 + + # check that the timestamp difference is the expected one + ts0 = client.get_block_timestamp(block=str(2)) + ts1 = client.get_block_timestamp(block=str(max_level)) + time_diff = (ts1 - ts0).total_seconds() + assert time_diff == BD * (max_level - 2) diff --git a/tests_python/tests_009/test_bootstrap.py b/tests_python/tests_009/test_bootstrap.py new file mode 100644 index 0000000000000000000000000000000000000000..3e65a0a746f51ac070365cef9ea4459581889e84 --- /dev/null +++ b/tests_python/tests_009/test_bootstrap.py @@ -0,0 +1,212 @@ +import time +import pytest +from launchers.sandbox import Sandbox +from . import protocol + + +LOG_LEVEL = {"validator.chain": "debug", "validator.peer": "debug"} + + +def params(threshold=0, latency=3): + return [ + '--sync-latency', + str(latency), + '--synchronisation-threshold', + str(threshold), + '--connections', + '100', + ] + + +@pytest.mark.baker +@pytest.mark.incremental +class TestThresholdZero: + """Threshold 0, peer always bootstrapped.""" + + def test_setup_network(self, sandbox: Sandbox): + sandbox.add_node(0, params=params(), log_levels=LOG_LEVEL) + sandbox.add_baker(0, 'bootstrap5', proto=protocol.DAEMON) + + def test_bootstrap(self, sandbox: Sandbox): + client = sandbox.client(0) + assert client.sync_state() == 'synced' + + +@pytest.mark.baker +@pytest.mark.multinode +@pytest.mark.incremental +class TestThresholdOne: + """First peer has threshold zero, second peer has threshold one""" + + def test_setup_network(self, sandbox: Sandbox): + sandbox.add_node(0, params=params(), log_levels=LOG_LEVEL) + protocol.activate(sandbox.client(0)) + sandbox.add_baker(0, 'bootstrap5', proto=protocol.DAEMON) + + def test_bootstrap(self, sandbox: Sandbox): + client = sandbox.client(0) + assert client.sync_state() == 'synced' + + def test_add_node(self, sandbox: Sandbox): + sandbox.add_node( + 1, params=params(1), log_levels=LOG_LEVEL, config_client=False + ) + sandbox.client(1).bootstrapped() + + +@pytest.mark.baker +@pytest.mark.multinode +@pytest.mark.incremental +class TestThresholdTwo: + def test_setup_network(self, sandbox: Sandbox): + sandbox.add_node(0, params=params(0), log_levels=LOG_LEVEL) + protocol.activate(sandbox.client(0)) + sandbox.add_baker(0, 'bootstrap5', proto=protocol.DAEMON) + + def test_add_nodes(self, sandbox: Sandbox): + sandbox.add_node( + 1, params=params(2), log_levels=LOG_LEVEL, config_client=False + ) + sandbox.add_node( + 2, params=params(2), log_levels=LOG_LEVEL, config_client=False + ) + sandbox.add_node( + 3, params=params(1), log_levels=LOG_LEVEL, config_client=False + ) + + @pytest.mark.timeout(5) + def test_node_3_bootstrapped(self, sandbox: Sandbox): + sandbox.client(3).bootstrapped() + + @pytest.mark.timeout(5) + def test_node_1_bootstrapped(self, sandbox: Sandbox): + sandbox.client(1).bootstrapped() + + +@pytest.mark.slow +@pytest.mark.baker +@pytest.mark.multinode +@pytest.mark.incremental +class TestStuck: + def test_setup_network(self, sandbox: Sandbox): + sandbox.add_node(0, params=params(), log_levels=LOG_LEVEL) + protocol.activate(sandbox.client(0)) + sandbox.add_baker(0, 'bootstrap5', proto=protocol.DAEMON) + + def test_kill_baker(self, sandbox: Sandbox): + """Bake a few blocks and kill baker""" + time.sleep(2) + sandbox.rm_baker(0, proto=protocol.DAEMON) + time.sleep(5) + + def test_progress(self, sandbox: Sandbox): + assert sandbox.client(0).get_level() >= 2 + + def test_add_node(self, sandbox: Sandbox): + sandbox.add_node( + 1, params=params(2), config_client=False, log_levels=LOG_LEVEL + ) + sandbox.add_node( + 2, params=params(2), config_client=False, log_levels=LOG_LEVEL + ) + + def test_all_nodes_boostrap(self, sandbox: Sandbox): + """Eventually, 1 and 2 are bootstrapped with the chain stuck. """ + sandbox.client(1).bootstrapped() + sandbox.client(2).bootstrapped() + assert sandbox.client(1).sync_state() == 'stuck' + assert sandbox.client(2).sync_state() == 'stuck' + + +@pytest.mark.baker +@pytest.mark.multinode +@pytest.mark.incremental +class TestSplitView: + def test_setup_network(self, sandbox: Sandbox): + sandbox.add_node(0, params=params(), log_levels=LOG_LEVEL) + protocol.activate(sandbox.client(0)) + sandbox.add_node( + 1, params=params(), config_client=False, log_levels=LOG_LEVEL + ) + sandbox.add_node( + 2, + params=params(2, latency=15), + config_client=False, + log_levels=LOG_LEVEL, + ) + sandbox.add_baker(0, 'bootstrap5', proto=protocol.DAEMON) + + @pytest.mark.timeout(10) + def test_all_nodes_boostrap(self, sandbox: Sandbox): + assert sandbox.client(0).sync_state() == 'synced' + assert sandbox.client(1).sync_state() == 'synced' + sandbox.client(2).bootstrapped() + + def test_pause(self): + time.sleep(2) + + def test_disconnect_node(self, sandbox: Sandbox): + """node 1 is disconnected from baker""" + sandbox.client(1).ban_peer(sandbox.node(0).p2p_port) + sandbox.client(0).ban_peer(sandbox.node(1).p2p_port) + + def test_sync_status(self, sandbox: Sandbox): + assert sandbox.client(0).sync_state() == 'synced' + assert sandbox.client(1).sync_state() == 'synced' + assert sandbox.client(2).sync_state() == 'synced' + + +NUM_NODES = 8 +RUNNING_TIME = 10 + + +@pytest.mark.baker +@pytest.mark.multinode +@pytest.mark.slow +@pytest.mark.incremental +class TestManyNodesBootstrap: + """Run many nodes, bake for a while, add a node and check it's bootstrapped + when it should be.""" + + def test_init(self, sandbox: Sandbox): + sandbox.add_node(0, params=params(), log_levels=LOG_LEVEL) + parameters = dict(protocol.PARAMETERS) + parameters["time_between_blocks"] = ["1", "0"] + protocol.activate(sandbox.client(0)) + sandbox.add_baker(0, 'bootstrap1', proto=protocol.DAEMON) + sandbox.add_node( + 1, params=params(), log_levels=LOG_LEVEL, config_client=False + ) + + def test_bootstrap(self, sandbox: Sandbox): + sandbox.client(0).bootstrapped() + sandbox.client(1).bootstrapped() + + def test_add_nodes(self, sandbox: Sandbox): + for i in range(2, NUM_NODES): + sandbox.add_node( + i, params=params(), config_client=False, log_levels=LOG_LEVEL + ) + + def test_let_baking(self): + time.sleep(RUNNING_TIME) + + def test_progress(self, sandbox, session): + cur_level = sandbox.client(NUM_NODES - 1).get_level() + assert cur_level > RUNNING_TIME // 2 # check progress + session['cur_level'] = cur_level + + @pytest.mark.timeout(50) + def test_add_one_more_node(self, sandbox, session): + new_node = NUM_NODES + sandbox.add_node( + new_node, + params=params(NUM_NODES), + config_client=False, + log_levels=LOG_LEVEL, + ) + time.sleep(1) + sandbox.client(new_node).p2p_stat() + sandbox.client(new_node).bootstrapped() + cur_level = session['cur_level'] + assert sandbox.client(new_node).get_level() >= cur_level diff --git a/tests_python/tests_009/test_client_without_node.py b/tests_python/tests_009/test_client_without_node.py new file mode 100644 index 0000000000000000000000000000000000000000..033c89c6d7b17bd85acad7d37919857aa4723091 --- /dev/null +++ b/tests_python/tests_009/test_client_without_node.py @@ -0,0 +1,433 @@ +"""Node-less tests for the client. + +Some client tests do not require a node running, nor a +persistent mockup environment. These can be placed here. +""" +import json +import os +import subprocess +import tempfile +from typing import List, Optional +import pytest +from client.client import Client +from tools.utils import assert_run_failure + +# Note that specifying "endpoint" and "web_port" is required +# for the final assertion of test_config_init_roundtrip to pass. That's because +# `config init -o` writes them even if unspecified by `--config-file` +# (it's a fine behavior, I just wanted to highlight it). +_INPUT_CONFIG_FILE = { + "confirmations": 1, + "endpoint": "http://127.0.0.1:8732", + "remote_signer": "http://127.0.0.2", + "web_port": 8080, + "password_filename": "/tmp/doesnt_exist", +} +_INPUT_CONFIG_FILES = [None, _INPUT_CONFIG_FILE] +_CMD_LINE_ARGS = { + "--endpoint": "http://127.0.0.1:9732", + "--wait": "3", + "--remote-signer": "http://10.0.0.2", + "--password-filename": "/tmp/doesnt_exist_either", +} +_CONFIG_FILE_FLAG = "--config-file" + + +@pytest.mark.client +class TestImportKeyMnemonic: + """ Checks that the keys are correctly imported from a mnemonic. """ + + @pytest.fixture + def mnemonic(self): + return ( + "seek paddle siege sting siege sick kidney " + + "detect coral because comfort long enforce napkin enter" + ) + + @pytest.fixture + def passphrase(self): + return "very_secure_passphrase" + + def test_import_simple(self, client: Client): + """ Tests a simple import. """ + mnemonic = "release easy pulp drop select attack false math cook \ +angry spin ostrich round dress acoustic" + prms = ["import", "keys", "from", "mnemonic", "zebra", "--force"] + stdin = mnemonic + "\n\n" + client.run_generic(prms, stdin=stdin) + addr = client.get_known_addresses() + assert addr.wallet["zebra"] == "tz1aGUKE72eN21iWztoDEeH4FeKaxWb7SAUb" + + def test_import_already_present_alias(self, client: Client, mnemonic): + """ Tests that importing fails if the alias is already present. """ + prms = [ + "import", + "keys", + "from", + "mnemonic", + "super_original", + "--force", + ] + stdin = mnemonic + "\n\n" + client.run_generic(prms, stdin=stdin) + prms = ["import", "keys", "from", "mnemonic", "super_original"] + expected_error = "The secret_key alias super_original already exists." + with assert_run_failure(expected_error): + client.run_generic(prms, stdin=stdin) + + def test_import_passphrase(self, client: Client, mnemonic, passphrase): + """ Tests an import where the user specifies a passphrase. """ + stdin = mnemonic + "\n" + passphrase + "\n" + prms = ["import", "keys", "from", "mnemonic", "key", "--force"] + client.run_generic(prms, stdin=stdin) + addr = client.get_known_addresses() + assert addr.wallet["key"] == "tz1QSF4TSVzaosgbaxnFJpRbs7798Skeb8Re" + + def test_encrypted(self, client: Client, mnemonic, passphrase): + """ Tests an import where the user wants to encrypt the key. """ + encrypt_pwd = "imgonnaencryptthiskeysohard" + stdin = ( + mnemonic + + "\n" + + passphrase + + "\n" + + encrypt_pwd + + "\n" + + encrypt_pwd + + "\n" + ) + prms = [ + "import", + "keys", + "from", + "mnemonic", + "cryptkey", + "--encrypt", + "--force", + ] + client.run_generic(prms, stdin=stdin) + addr = client.get_known_addresses() + pkh = addr.wallet["cryptkey"] + secret_key = client.show_address( + "cryptkey", show_secret=True + ).secret_key + assert secret_key is not None + assert secret_key.startswith("encrypted:") + assert pkh == "tz1QSF4TSVzaosgbaxnFJpRbs7798Skeb8Re" + + def test_gen_key_from_menmonic_bad_mnemonic(self, client: Client): + """ Tests that the command fails if the user gives a bad mnemonic. """ + prms = ["import", "keys", "from", "mnemonic", "alias", "--force"] + stdin = "hello\n\n" + expected_error = '"hello" is not a valid BIP39 mnemonic.' + with assert_run_failure(expected_error): + client.run_generic(prms, stdin=stdin) + + +@pytest.mark.client +class TestChainId: + def test_chain_id_block_hash(self, nodeless_client: Client): + block_hash = 'BKyFui5WPY1n3e9aKF3qd2kGBKBtHu3rtm5miYFnUagJC1BdHTF' + prms = ['compute', 'chain', 'id', 'from', 'block', 'hash', block_hash] + assert nodeless_client.run(prms).strip() == 'NetXuwrXPL4VeX5' + + def test_chain_id_seed(self, nodeless_client: Client): + seed = 'choucroute' + prms = ['compute', 'chain', 'id', 'from', 'seed', seed] + assert nodeless_client.run(prms).strip() == 'NetXLGmPi3c5DXf' + + +def _write_config_file( + client: Client, filename: str, config_dict: Optional[dict] +): + """Writes `config_dict` to `filename`. Returns the json effectively + written""" + assert client is not None + assert filename is not None + assert config_dict is not None + + augmented_dict = dict(config_dict) # Copy for safety + # We need to set base_dir, it's required in the config file + augmented_dict["base_dir"] = client.base_dir + with open(filename, 'w') as handle: + json.dump(augmented_dict, handle) + + return augmented_dict + + +def _with_config_file_cmd(config_file: Optional[str], cmd: List[str]): + """Prefixes `cmd` with ["--config-file", config_file] if + config_file is not None""" + return ([_CONFIG_FILE_FLAG, config_file] if config_file else []) + cmd + + +def _gen_assert_msg(flag, sent, received): + result = f"Json sent with --{flag} differs from" + result += " json received" + result += f"\nJson sent is:\n{sent}" + result += f"\nwhile json received is:\n{received}" + + +@pytest.mark.client +@pytest.mark.parametrize('config_dict', _INPUT_CONFIG_FILES) +class TestConfigInit: + def test_config_init( + self, nodeless_client: Client, config_dict: Optional[dict] + ): + """ + Tests that calling + `[--config-file config_dict]? config init -o tmp_file` + works and yields valid json. + """ + try: + out_file = tempfile.mktemp(prefix='tezos-client.config_file') + in_file = None + + if config_dict is not None: + in_file = tempfile.mktemp(prefix='tezos-client.config_file') + _write_config_file(nodeless_client, in_file, config_dict) + + cmd = _with_config_file_cmd( + in_file, ["config", "init", "-o", out_file] + ) + nodeless_client.run(cmd) + # Try loading the file as json, to check it is valid + with open(out_file) as handle: + json.load(handle) + finally: + if in_file is not None: + os.remove(in_file) + os.remove(out_file) + + def test_config_init_roundtrip( + self, nodeless_client: Client, config_dict: Optional[dict] + ): + """Tests that calling `config init -o tmp_file` and + feeding its result to `tezos-client --config-file` works + and yields the same result (i.e. calling `tezos-client + --config-file tmp_file config init -o tmp_file2 yields + a `tmp_file2` that is similar to `tmp_file`). + + `config_dict` specifies the content of the initial config file + to use or None not to specify one. + """ + try: + if config_dict is None: + # Take initial json from default output of `config init` + + tmp_file1 = tempfile.mktemp(prefix='tezos-client.config_file') + cmd = ["config", "init", "-o", tmp_file1] + nodeless_client.run(cmd) + with open(tmp_file1) as handle: + json1 = json.load(handle) + + # Execute an arbitrary effectless command: + list_protos = ["list", "understood", "protocols"] + # This checks that + # `--config-file tmp_file1 arbitrary command` works + cmd = _with_config_file_cmd(tmp_file1, list_protos) + nodeless_client.run(cmd) + else: + # Take initial json from config_dict + + # Write config_dict to a file + tmp_file1 = tempfile.mktemp(prefix='tezos-client.config_file') + json1 = _write_config_file( + nodeless_client, tmp_file1, config_dict + ) + + # Execute `config init -o` + tmp_file2 = tempfile.mktemp(prefix='tezos-client.config_file') + cmd = _with_config_file_cmd( + tmp_file1, ["config", "init", "-o", tmp_file2] + ) + nodeless_client.run(cmd) + + # Load file generated by `config init -o` + with open(tmp_file2) as handle: + json2 = json.load(handle) + + # and finally check that the json generated by `config init -o` + # matches the input data (either the default one or the one + # specified with --config-file) + assert json1 == json2, _gen_assert_msg( + _CONFIG_FILE_FLAG, json1, json2 + ) + finally: + os.remove(tmp_file1) + os.remove(tmp_file2) + + +def _cmd_line_flag_to_json_field(cmd_line_flag: str): + if cmd_line_flag == "--wait": + return "confirmations" + result = cmd_line_flag + if cmd_line_flag.startswith("--"): + result = result[2:] + return result.replace("-", "_") + + +@pytest.mark.client +@pytest.mark.parametrize('config_dict', _INPUT_CONFIG_FILES) +class TestConfigShow: + """ Tests of `tezos-client config show` """ + + def test_config_show( + self, nodeless_client: Client, config_dict: Optional[dict] + ): + """ + Tests that calling `config show` works, with or without + specifying `--config-file` + """ + try: + tmp_file = None + if config_dict is not None: + tmp_file = tempfile.mktemp(prefix='tezos-client.config_file') + _write_config_file(nodeless_client, tmp_file, config_dict) + + cmd = _with_config_file_cmd(tmp_file, ["config", "show"]) + nodeless_client.run(cmd) + finally: + if tmp_file is not None: + os.remove(tmp_file) + + @pytest.mark.parametrize('cmd_line_args', [{}, _CMD_LINE_ARGS]) + def test_config_show_roundtrip( + self, + nodeless_client: Client, + config_dict: Optional[dict], + cmd_line_args: dict, + ): + """ + Tests calling `config show` with or without `--config-file` + and with some command line parameters (`cmd_line_arg`). It + then parses the output to check its valid json and to check + that command line parameters were honored. + + Then it feeds this output to a new call to `--config-file file + config show` and checks that the json returned by this second call + agrees with what was specified by `file`. + + This is a roundtrip test using a small matrix. + """ + try: + in_file1 = None + in_file2 = None + if config_dict is not None: + in_file1 = tempfile.mktemp(prefix='tezos-client.config_file') + _write_config_file(nodeless_client, in_file1, config_dict) + + cmd = [] + # Pass command line parameters + for (flag, value) in cmd_line_args.items(): + cmd += [flag, value] + cmd += ["config", "show"] + cmd = _with_config_file_cmd(in_file1, cmd) + # Take standard output + (stdout, _, _) = nodeless_client.run_generic(cmd) + + output_json1 = json.loads(stdout) + # Verify that command line parameters were honored + for (flag, value) in cmd_line_args.items(): + input_value = cmd_line_args[flag] + assert isinstance(input_value, str) + output_value = output_json1[_cmd_line_flag_to_json_field(flag)] + output_value = str(output_value) + err_msg = ( + f"Value of command line flag {flag} is not honored:" + f" passed {input_value} but" + f" config show yielded {output_value}" + ) + assert output_value == input_value, err_msg + in_file2 = tempfile.mktemp(prefix='tezos-client.config_file') + # Write output of first call to `config show` to disk, + # to pass it to second call below + with open(in_file2, 'w') as handle: + handle.write(json.dumps(output_json1)) + + # Use previous ouput file as input now + cmd = _with_config_file_cmd(in_file2, ["config", "show"]) + (stdout, _, _) = nodeless_client.run_generic(cmd) + + output_json2 = json.loads(stdout) + + # And finally check that the final output matches the input + assert output_json1 == output_json2, _gen_assert_msg( + _CONFIG_FILE_FLAG, output_json1, output_json2 + ) + finally: + for in_file in [in_file1, in_file2]: + if in_file is not None: + os.remove(in_file) + + +@pytest.mark.client +class TestConfigValid: + """ Tests of validity of tezos-client config """ + + def test_config_node_port(self, nodeless_client: Client): + """ + Tests that calling `config show` works, with a valid node port + """ + self._run_config_show_with_node_port(nodeless_client, 8732) + self._run_config_show_with_node_port(nodeless_client, 58732) + pytest.raises( + subprocess.CalledProcessError, + self._run_config_show_with_node_port, + nodeless_client, + 158732, + ) + pytest.raises( + subprocess.CalledProcessError, + self._run_config_show_with_node_port, + nodeless_client, + -8732, + ) + + def test_config_web_port(self, nodeless_client: Client): + """ + Tests that calling `config show` works, with a valid node port + """ + self._run_config_show_with_web_port(nodeless_client, 8732) + self._run_config_show_with_web_port(nodeless_client, 58732) + pytest.raises( + subprocess.CalledProcessError, + self._run_config_show_with_web_port, + nodeless_client, + 158732, + ) + pytest.raises( + subprocess.CalledProcessError, + self._run_config_show_with_web_port, + nodeless_client, + -8732, + ) + + def _run_config_show_with_temp_config_file( + self, nodeless_client: Client, config_dict: dict + ): + try: + tmp_file = tempfile.mktemp(prefix='tezos-client.config_file') + _write_config_file(nodeless_client, tmp_file, config_dict) + + cmd = _with_config_file_cmd(tmp_file, ["config", "show"]) + nodeless_client.run(cmd) + finally: + if tmp_file is not None: + os.remove(tmp_file) + + def _run_config_show_with_node_port( + self, nodeless_client: Client, port: int + ): + config_dict = {"node_port": port} + self._run_config_show_with_temp_config_file( + nodeless_client, config_dict + ) + + def _run_config_show_with_web_port( + self, nodeless_client: Client, port: int + ): + config_dict = {"web_port": port} + self._run_config_show_with_temp_config_file( + nodeless_client, config_dict + ) diff --git a/tests_python/tests_009/test_codec.py b/tests_python/tests_009/test_codec.py new file mode 100644 index 0000000000000000000000000000000000000000..bb87d8b037f7ac6bb59e8e0a99afb6d7583c05cf --- /dev/null +++ b/tests_python/tests_009/test_codec.py @@ -0,0 +1,23 @@ +from typing import Any +import pytest +from codec.codec import Codec +from tools import paths + +CODEC_BIN = paths.TEZOS_HOME + "tezos-codec" + +ENCODINGS = [ + ( + "network_version", + {"p2p_version": 0, "distributed_db_version": 1, "chain_name": "main"}, + ) +] + + +@pytest.mark.codec +class TestCodec: + @pytest.mark.parametrize("encoding_name, data", ENCODINGS) + def test_codec_encode_decode(self, encoding_name: str, data: Any): + codec = Codec(CODEC_BIN) + data_encoded = codec.encode(encoding_name, data_json=data) + data_decoded = codec.decode(encoding_name, data=data_encoded) + assert data_decoded == data diff --git a/tests_python/tests_009/test_contract.py b/tests_python/tests_009/test_contract.py new file mode 100644 index 0000000000000000000000000000000000000000..ab36a10e05bb4d66215730dd578ab3a474a56c57 --- /dev/null +++ b/tests_python/tests_009/test_contract.py @@ -0,0 +1,1533 @@ +import os +import re +import json +import itertools +from typing import List, Union, Any +import pytest + +from client.client import Client +from tools import utils +from tools.constants import IDENTITIES +from .contract_paths import ( + CONTRACT_PATH, + ILLTYPED_CONTRACT_PATH, + all_contracts, + all_legacy_contracts, +) + +BAKE_ARGS = ['--minimal-timestamp'] + + +def file_basename(path): + return os.path.splitext(os.path.basename(path))[0] + + +# Generic piece of code to originate a contract +def originate( + client, + session, + contract, + init_storage, + amount, + contract_name=None, + sender='bootstrap1', + baker='bootstrap5', + arguments=None, +): + if contract_name is None: + contract_name = file_basename(contract) + + args = ['--init', init_storage, '--burn-cap', '10.0'] + if arguments is not None: + args += arguments + origination = client.originate( + contract_name, amount, sender, contract, args + ) + session['contract'] = origination.contract + print(origination.contract) + client.bake(baker, BAKE_ARGS) + assert utils.check_block_contains_operations( + client, [origination.operation_hash] + ) + return origination + + +@pytest.mark.contract +@pytest.mark.incremental +class TestManager: + def test_manager_origination(self, client: Client, session: dict): + path = os.path.join(CONTRACT_PATH, 'entrypoints', 'manager.tz') + pubkey = IDENTITIES['bootstrap2']['identity'] + originate(client, session, path, f'"{pubkey}"', 1000) + originate( + client, session, path, f'"{pubkey}"', 1000, contract_name="manager2" + ) + + def test_delegatable_origination(self, client: Client, session: dict): + path = os.path.join( + CONTRACT_PATH, 'entrypoints', 'delegatable_target.tz' + ) + pubkey = IDENTITIES['bootstrap2']['identity'] + originate( + client, session, path, f'Pair "{pubkey}" (Pair "hello" 45)', 1000 + ) + + def test_target_with_entrypoints_origination(self, client: Client, session): + path = os.path.join( + CONTRACT_PATH, 'entrypoints', 'big_map_entrypoints.tz' + ) + originate( + client, session, path, 'Pair {} {}', 1000, contract_name='target' + ) + + def test_target_without_entrypoints_origination( + self, client: Client, session + ): + path = os.path.join( + CONTRACT_PATH, 'entrypoints', 'no_entrypoint_target.tz' + ) + originate( + client, + session, + path, + 'Pair "hello" 42', + 1000, + contract_name='target_no_entrypoints', + ) + + def test_target_without_default_origination(self, client: Client, session): + path = os.path.join( + CONTRACT_PATH, 'entrypoints', 'no_default_target.tz' + ) + originate( + client, + session, + path, + 'Pair "hello" 42', + 1000, + contract_name='target_no_default', + ) + + def test_target_with_root_origination(self, client: Client, session): + path = os.path.join(CONTRACT_PATH, 'entrypoints', 'rooted_target.tz') + originate( + client, + session, + path, + 'Pair "hello" 42', + 1000, + contract_name='rooted_target', + ) + + def test_manager_set_delegate(self, client: Client): + client.set_delegate('manager', 'bootstrap2', []) + client.bake('bootstrap5', BAKE_ARGS) + bootstrap2_pkh = IDENTITIES['bootstrap2']['identity'] + client.set_delegate('delegatable_target', bootstrap2_pkh, []) + client.bake('bootstrap5', BAKE_ARGS) + delegate = IDENTITIES['bootstrap2']['identity'] + assert client.get_delegate('manager', []).delegate == delegate + assert ( + client.get_delegate('delegatable_target', []).delegate == delegate + ) + client.set_delegate('manager', 'bootstrap3', []) + client.bake('bootstrap5', BAKE_ARGS) + client.set_delegate('delegatable_target', 'bootstrap3', []) + client.bake('bootstrap5', BAKE_ARGS) + delegate = IDENTITIES['bootstrap3']['identity'] + assert client.get_delegate('manager', []).delegate == delegate + assert ( + client.get_delegate('delegatable_target', []).delegate == delegate + ) + + def test_manager_withdraw_delegate(self, client: Client): + client.withdraw_delegate('manager', []) + client.bake('bootstrap5', BAKE_ARGS) + client.withdraw_delegate('delegatable_target', []) + client.bake('bootstrap5', BAKE_ARGS) + assert client.get_delegate('manager', []).delegate is None + assert client.get_delegate('delegatable_target', []).delegate is None + + def test_transfer_to_manager(self, client: Client): + balance = client.get_mutez_balance('manager') + balance_bootstrap = client.get_mutez_balance('bootstrap2') + amount = 10.001 + amount_mutez = utils.mutez_of_tez(amount) + client.transfer( + amount, + 'bootstrap2', + 'manager', + ['--gas-limit', f'{128 * 15450 + 108}'], + ) + client.bake('bootstrap5', BAKE_ARGS) + new_balance = client.get_mutez_balance('manager') + new_balance_bootstrap = client.get_mutez_balance('bootstrap2') + fee = 0.000548 + fee_mutez = utils.mutez_of_tez(fee) + assert balance + amount_mutez == new_balance + assert ( + balance_bootstrap - fee_mutez - amount_mutez + == new_balance_bootstrap + ) + + def test_simple_transfer_from_manager_to_implicit(self, client: Client): + balance = client.get_mutez_balance('manager') + balance_bootstrap = client.get_mutez_balance('bootstrap2') + amount = 10.1 + amount_mutez = utils.mutez_of_tez(amount) + client.transfer( + amount, + 'manager', + 'bootstrap2', + ['--gas-limit', f'{128 * 26350 + 12}'], + ) + client.bake('bootstrap5', BAKE_ARGS) + new_balance = client.get_mutez_balance('manager') + new_balance_bootstrap = client.get_mutez_balance('bootstrap2') + fee = 0.000794 + fee_mutez = utils.mutez_of_tez(fee) + assert balance - amount_mutez == new_balance + assert ( + balance_bootstrap + amount_mutez - fee_mutez + == new_balance_bootstrap + ) + + def test_transfer_from_manager_to_manager(self, client: Client): + balance = client.get_mutez_balance('manager') + balance_dest = client.get_mutez_balance('manager2') + balance_bootstrap = client.get_mutez_balance('bootstrap2') + amount = 10 + amount_mutez = utils.mutez_of_tez(amount) + client.transfer( + amount, + 'manager', + 'manager2', + ['--gas-limit', f'{128 * 44950 + 112}'], + ) + client.bake('bootstrap5', BAKE_ARGS) + new_balance = client.get_mutez_balance('manager') + new_balance_dest = client.get_mutez_balance('manager2') + new_balance_bootstrap = client.get_mutez_balance('bootstrap2') + fee = 0.001124 + fee_mutez = utils.mutez_of_tez(fee) + assert balance_bootstrap - fee_mutez == new_balance_bootstrap + assert balance - amount_mutez == new_balance + assert balance_dest + amount_mutez == new_balance_dest + + def test_transfer_from_manager_to_default(self, client: Client): + client.transfer( + 10, 'manager', 'bootstrap2', ['--entrypoint', 'default'] + ) + client.bake('bootstrap5', BAKE_ARGS) + client.transfer(10, 'manager', 'manager', ['--entrypoint', 'default']) + client.bake('bootstrap5', BAKE_ARGS) + + def test_transfer_from_manager_to_target(self, client: Client): + client.transfer(10, 'manager', 'target', ['--burn-cap', '0.356']) + client.bake('bootstrap5', BAKE_ARGS) + + def test_transfer_from_manager_to_entrypoint_with_args( + self, client: Client + ): + arg = 'Pair "hello" 42' + # using 'transfer' + client.transfer( + 0, + 'manager', + 'target', + ['--entrypoint', 'add_left', '--arg', arg, '--burn-cap', '0.067'], + ) + client.bake('bootstrap5', BAKE_ARGS) + client.transfer( + 0, + 'manager', + 'target', + ['--entrypoint', 'mem_left', '--arg', '"hello"'], + ) + client.bake('bootstrap5', BAKE_ARGS) + + # using 'call' + client.call( + 'manager', + 'target', + ['--entrypoint', 'add_left', '--arg', arg, '--burn-cap', '0.067'], + ) + client.bake('bootstrap5', BAKE_ARGS) + client.call( + 'manager', + 'target', + ['--entrypoint', 'mem_left', '--arg', '"hello"'], + ) + client.bake('bootstrap5', BAKE_ARGS) + + def test_transfer_from_manager_no_entrypoint_with_args( + self, client: Client + ): + arg = 'Left Unit' + client.transfer(0, 'manager', 'target_no_entrypoints', ['--arg', arg]) + client.bake('bootstrap5', BAKE_ARGS) + + client.call('manager', 'target_no_entrypoints', ['--arg', arg]) + client.bake('bootstrap5', BAKE_ARGS) + + def test_transfer_from_manager_to_no_default_with_args( + self, client: Client + ): + arg = 'Left Unit' + client.transfer(0, 'manager', 'target_no_default', ['--arg', arg]) + client.bake('bootstrap5', BAKE_ARGS) + + client.call('manager', 'target_no_default', ['--arg', arg]) + client.bake('bootstrap5', BAKE_ARGS) + + def test_transfer_from_manager_to_rooted_target_with_args( + self, client: Client + ): + arg = 'Left Unit' + client.transfer( + 0, + 'manager', + 'rooted_target', + ['--arg', arg, '--entrypoint', 'root'], + ) + client.bake('bootstrap5', BAKE_ARGS) + + client.call( + 'manager', 'rooted_target', ['--arg', arg, '--entrypoint', 'root'] + ) + client.bake('bootstrap5', BAKE_ARGS) + + def test_transfer_json_to_entrypoint_with_args(self, client): + balance = client.get_mutez_balance('manager') + balance_bootstrap = client.get_mutez_balance('bootstrap2') + fee = 0.0123 + fee_mutez = utils.mutez_of_tez(fee) + json_obj = [ + { + "destination": "target", + "amount": "0", + "fee": str(fee), + "gas-limit": "65942", + "storage-limit": "1024", + "arg": 'Pair "hello" 42', + "entrypoint": "add_left", + } + ] + json_ops = json.dumps(json_obj, separators=(',', ':')) + client.run(client.cmd_batch('manager', json_ops)) + client.bake('bootstrap5', BAKE_ARGS) + new_balance = client.get_mutez_balance('manager') + new_balance_bootstrap = client.get_mutez_balance('bootstrap2') + assert balance == new_balance + assert balance_bootstrap - fee_mutez == new_balance_bootstrap + + def test_multiple_transfers(self, client): + balance = client.get_mutez_balance('manager') + balance_bootstrap2 = client.get_mutez_balance('bootstrap2') + balance_bootstrap3 = client.get_mutez_balance('bootstrap3') + amount_2 = 10.1 + amount_mutez_2 = utils.mutez_of_tez(amount_2) + amount_3 = 11.01 + amount_mutez_3 = utils.mutez_of_tez(amount_3) + json_obj = [ + {"destination": "bootstrap2", "amount": str(amount_2)}, + {"destination": "bootstrap3", "amount": str(amount_3)}, + ] + json_ops = json.dumps(json_obj, separators=(',', ':')) + client.run(client.cmd_batch('manager', json_ops)) + client.bake('bootstrap5', BAKE_ARGS) + new_balance = client.get_mutez_balance('manager') + new_balance_bootstrap2 = client.get_mutez_balance('bootstrap2') + new_balance_bootstrap3 = client.get_mutez_balance('bootstrap3') + fee_mutez = 794 + 698 + assert balance - amount_mutez_2 - amount_mutez_3 == new_balance + assert ( + balance_bootstrap2 + amount_mutez_2 - fee_mutez + == new_balance_bootstrap2 + ) + assert balance_bootstrap3 + amount_mutez_3 == new_balance_bootstrap3 + + +# This test to verifies contract execution order. There are 3 +# contracts: Storer, Caller, and Appender. Storer appends its argument +# to storage. Caller calls the list of unit contracts in its +# storage. Appender calls the string contract in its storage with a +# stored argument. +# +# For each test, there is one unique Storer. Each test is +# parameterized by a tree and the expected final storage of the +# Storer. A leaf in the tree is a string. Inner nodes are lists of +# leafs/inner nodes. The test maps maps over this tree to build a +# tree of contracts. Leaf nodes map to Appender contracts calling +# the Storer. Inner nodes map to Caller contract that calling +# children. +# +# Example. Given the tree: ["A", ["B"], "C"], we obtain +# Caller([Appender("A"), Caller([Appender("B")]), Appender("C")]) +# Before the protocol 009, contract execution order was in BFS +# In BFS, Storer would've ended up with storage ACB. +# In DFS, Storer will end up with storage ABC. +@pytest.mark.contract +@pytest.mark.incremental +class TestExecutionOrdering: + STORER = f'{CONTRACT_PATH}/mini_scenarios/execution_order_storer.tz' + CALLER = f'{CONTRACT_PATH}/mini_scenarios/execution_order_caller.tz' + APPENDER = f'{CONTRACT_PATH}/mini_scenarios/execution_order_appender.tz' + + def originate_storer(self, client: Client, session: dict): + origination = originate( + client, session, self.STORER, '""', 0, arguments=['--force'] + ) + session['storer'] = origination.contract + client.bake('bootstrap3', BAKE_ARGS) + return origination.contract + + def originate_appender( + self, client: Client, session: dict, storer: str, argument: str + ): + origination = originate( + client, + session, + self.APPENDER, + f'Pair "{storer}" "{argument}"', + 0, + contract_name=f'appender-{argument}', + arguments=['--force'], + ) + session[f'appender.{argument}'] = origination.contract + client.bake('bootstrap3', BAKE_ARGS) + return origination.contract + + def originate_caller( + self, client: Client, session: dict, callees: List[str] + ): + storage = "{" + '; '.join(map('"{}"'.format, callees)) + "}" + origination = originate( + client, + session, + self.CALLER, + storage, + 0, + contract_name=f'caller-{hash(storage)}', + ) + client.bake('bootstrap3', BAKE_ARGS) + return origination.contract + + @pytest.mark.parametrize( + "tree, expected", + [ + # before 009, the result should be "DABCEFG". + ([["A", "B", "C"], "D", ["E", "F", "G"]], "ABCDEFG"), + # before 009, the result should be "ACB". + ([["A", ["B"], "C"]], "ABC"), + # before 009, the result should be "ABDC". + ([["A", ["B", ["C"], "D"]]], "ABCD"), + ([], ""), + ], + ) + def test_ordering( + self, + client: Client, + session: dict, + # approximation of recursive type annotation + tree: Union[str, List[Any]], + expected: str, + ): + storer = self.originate_storer(client, session) + + def deploy_tree(tree: Union[str, List[Any]]) -> str: + # leaf + if isinstance(tree, str): + # deploy and return caller str + return self.originate_appender(client, session, storer, tree) + # inner node + children = list(map(deploy_tree, tree)) + return self.originate_caller(client, session, children) + + root = deploy_tree(tree) + + client.transfer( + 0, + 'bootstrap2', + root, + ["--burn-cap", "5"], + ) + client.bake('bootstrap3', ["--minimal-timestamp"]) + assert client.get_storage(storer) == '"{}"'.format(expected) + + +@pytest.mark.slow +@pytest.mark.contract +class TestContracts: + """Test type checking and execution of a bunch of contracts""" + + @pytest.mark.parametrize("contract", all_contracts()) + def test_typecheck(self, client: Client, contract): + assert contract.endswith( + '.tz' + ), "test contract should have .tz extension" + client.typecheck(os.path.join(CONTRACT_PATH, contract)) + + @pytest.mark.parametrize("contract", all_legacy_contracts()) + def test_deprecated_typecheck_breaks(self, client, contract): + if contract in [ + "legacy/create_contract.tz", + "legacy/create_contract_flags.tz", + "legacy/create_contract_rootname.tz", + ]: + with utils.assert_run_failure(r'ill-typed script'): + client.typecheck(os.path.join(CONTRACT_PATH, contract)) + else: + with utils.assert_run_failure(r'Use of deprecated instruction'): + client.typecheck(os.path.join(CONTRACT_PATH, contract)) + + @pytest.mark.parametrize("contract", all_legacy_contracts()) + def test_deprecated_typecheck_in_legacy(self, client, contract): + if contract in [ + "legacy/create_contract.tz", + "legacy/create_contract_flags.tz", + "legacy/create_contract_rootname.tz", + ]: + with utils.assert_run_failure(r'ill-typed script'): + client.typecheck( + os.path.join(CONTRACT_PATH, contract), legacy=True + ) + else: + with utils.assert_run_failure(r'Use of deprecated instruction'): + client.typecheck( + os.path.join(CONTRACT_PATH, contract), legacy=True + ) + + @pytest.mark.parametrize( + "contract,error_pattern", + [ + # operations cannot be PACKed + ( + "pack_operation.tz", + r'operation type forbidden in parameter, storage and constants', + ), + # big_maps cannot be PACKed + ( + "pack_big_map.tz", + r'big_map or sapling_state type not expected here', + ), + ( + "invalid_self_entrypoint.tz", + r'Contract has no entrypoint named D', + ), + ("contract_annotation_default.tz", r'unexpected annotation'), + # Missing field + ( + "missing_only_storage_field.tz", + r'Missing contract field: storage', + ), + ("missing_only_code_field.tz", r'Missing contract field: code'), + ( + "missing_only_parameter_field.tz", + r'Missing contract field: parameter', + ), + ( + "missing_parameter_and_storage_fields.tz", + r'Missing contract field: parameter', + ), + # Duplicated field + ( + "multiple_parameter_field.tz", + r'duplicate contract field: parameter', + ), + ("multiple_code_field.tz", r'duplicate contract field: code'), + ("multiple_storage_field.tz", r'duplicate contract field: storage'), + # The first duplicated field is reported, storage in this case + ( + "multiple_storage_and_code_fields.tz", + r'duplicate contract field: storage', + ), + # error message for set update on non-comparable type + ( + "set_update_non_comparable.tz", + r'Type nat is not compatible with type list operation', + ), + # error message for the arity of the chain_id type + ( + "chain_id_arity.tz", + r'primitive chain_id expects 0 arguments but is given 1', + ), + # error message for DIP over the limit + ("big_dip.tz", r'expected a positive 10-bit integer'), + # error message for DROP over the limit + ("big_drop.tz", r'expected a positive 10-bit integer'), + # error message for set update on non-comparable type + ( + "set_update_non_comparable.tz", + r'Type nat is not compatible with type list operation', + ), + # error message for attempting to push a value of type never + ("never_literal.tz", r'type never has no inhabitant.'), + # field annotation mismatch with UNPAIR + ( + "unpair_field_annotation_mismatch.tz", + r'The field access annotation does not match', + ), + # COMB, UNCOMB, and DUP cannot take 0 as argument + ("comb0.tz", r"PAIR expects an argument of at least 2"), + ("comb1.tz", r"PAIR expects an argument of at least 2"), + ("uncomb0.tz", r"UNPAIR expects an argument of at least 2"), + ("uncomb1.tz", r"UNPAIR expects an argument of at least 2"), + ("dup0.tz", r"DUP n expects an argument of at least 1"), + ( + "push_big_map_with_id_with_parens.tz", + r"big_map or sapling_state type not expected here", + ), + ( + "push_big_map_with_id_without_parens.tz", + r"primitive PUSH expects 2 arguments but is given 4", + ), + # sapling_state is not packable + ( + "pack_sapling_state.tz", + r"big_map or sapling_state type not expected here", + ), + # sapling_state is not packable + ( + "unpack_sapling_state.tz", + r"big_map or sapling_state type not expected here", + ), + # Ticket duplication attempt + ("ticket_dup.tz", r'DUP used on the non-dupable type ticket nat'), + # error message for ticket unpack + ("ticket_unpack.tz", r'Ticket in unauthorized position'), + # error message for attempting to use APPLY to capture a ticket + ("ticket_apply.tz", r'Ticket in unauthorized position'), + # error message for attempting to wrap a ticket in a ticket + ( + "ticket_in_ticket.tz", + r'comparable type expected.Type ticket unit is not comparable', + ), + ], + ) + def test_ill_typecheck(self, client: Client, contract, error_pattern): + with utils.assert_run_failure(error_pattern): + client.typecheck(os.path.join(ILLTYPED_CONTRACT_PATH, contract)) + + def test_zero_transfer_to_implicit_contract(self, client): + pubkey = IDENTITIES['bootstrap3']['identity'] + err = ( + 'Transaction of 0ꜩ towards a contract without code are ' + rf'forbidden \({pubkey}\).' + ) + with utils.assert_run_failure(err): + client.transfer(0, 'bootstrap2', 'bootstrap3', []) + + def test_zero_transfer_to_nonexistent_contract(self, client): + nonexistent = "KT1Fcq4inD44aMhmUiTEHR1QMQwJT7p2u641" + err = rf'Contract {nonexistent} does not exist' + with utils.assert_run_failure(err): + client.transfer(0, 'bootstrap2', nonexistent, []) + + +FIRST_EXPLOSION = ''' +{ parameter unit; + storage unit; + code{ DROP; PUSH nat 0 ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DROP ; UNIT ; NIL operation ; PAIR} } +''' + + +# FIRST_EXPLOSION costs a large amount of gas just for typechecking. +# FIRST_EXPLOSION_BIGTYPE type size exceeds the protocol set bound. +FIRST_EXPLOSION_BIGTYPE = ''' +{ parameter unit; + storage unit; + code{ DROP; PUSH nat 0 ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DUP ; PAIR ; + DROP ; UNIT ; NIL operation ; PAIR} } +''' + + +SECOND_EXPLOSION = ''' +{ parameter (list int) ; + storage (list (list (list int))) ; + code { CAR ; DIP { NIL (list int) } ; + DUP ; ITER { DROP ; DUP ; DIP { CONS } } ; + DROP ; DIP { NIL (list (list int)) } ; + DUP ; ITER { DROP ; DUP ; DIP { CONS } } ; + DROP ; NIL operation ; PAIR } } +''' + + +@pytest.mark.contract +class TestGasBound: + def test_write_contract(self, tmpdir, session: dict): + items = { + 'first_explosion.tz': FIRST_EXPLOSION, + 'first_explosion_bigtype.tz': FIRST_EXPLOSION_BIGTYPE, + 'second_explosion.tz': SECOND_EXPLOSION, + }.items() + for name, script in items: + contract = f'{tmpdir}/{name}' + with open(contract, 'w') as contract_file: + contract_file.write(script) + session[name] = contract + + def test_originate_first_explosion(self, client: Client, session: dict): + name = 'first_explosion.tz' + contract = session[name] + client.typecheck(contract) + args = ['-G', f'{1870}', '--burn-cap', '10'] + + expected_error = "Gas limit exceeded during typechecking or execution" + with utils.assert_run_failure(expected_error): + client.originate(f'{name}', 0, 'bootstrap1', contract, args) + + def test_originate_big_type(self, client: Client, session: dict): + name = 'first_explosion_bigtype.tz' + contract = session[name] + + # We could not be bothered with finding how to escape parentheses + # so we put dots + expected_error = "type size .1023. exceeded maximum type size .1000." + with utils.assert_run_failure(expected_error): + client.typecheck(contract) + + def test_originate_second_explosion(self, client: Client, session: dict): + name = 'second_explosion.tz' + contract = session[name] + storage = '{}' + inp = '{1;2;3;4;5;6;7;8;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1}' + client.run_script(contract, storage, inp) + + def test_originate_second_explosion_fail( + self, client: Client, session: dict + ): + name = 'second_explosion.tz' + contract = session[name] + storage = '{}' + inp = ( + '{1;2;3;4;5;6;7;8;9;0;1;2;3;4;5;6;7;1;1;1;1;1;1;1;1;1;1;1' + + ';1;1;1;1;1;1;1;1;1;1;1;1;1;1}' + ) + + expected_error = ( + "Cannot serialize the resulting storage" + + " value within the provided gas bounds." + ) + with utils.assert_run_failure(expected_error): + client.run_script(contract, storage, inp, gas=9290) + + def test_typecheck_map_dup_key(self, client: Client): + + expected_error = ( + 'Map literals cannot contain duplicate' + + ' keys, however a duplicate key was found' + ) + with utils.assert_run_failure(expected_error): + client.typecheck_data('{ Elt 0 1 ; Elt 0 1}', '(map nat nat)') + + def test_typecheck_map_bad_ordering(self, client: Client): + + expected_error = ( + "Keys in a map literal must be in strictly" + + " ascending order, but they were unordered in literal" + ) + with utils.assert_run_failure(expected_error): + client.typecheck_data( + '{ Elt 0 1 ; Elt 10 1 ; Elt 5 1 }', '(map nat nat)' + ) + + def test_typecheck_set_bad_ordering(self, client: Client): + + expected_error = ( + "Values in a set literal must be in strictly" + + " ascending order, but they were unordered in literal" + ) + with utils.assert_run_failure(expected_error): + client.typecheck_data('{ "A" ; "C" ; "B" }', '(set string)') + + def test_typecheck_set_no_duplicates(self, client: Client): + expected_error = ( + "Set literals cannot contain duplicate values," + + " however a duplicate value was found" + ) + with utils.assert_run_failure(expected_error): + client.typecheck_data('{ "A" ; "B" ; "B" }', '(set string)') + + +@pytest.mark.contract +class TestChainId: + def test_chain_id_opcode(self, client: Client, session: dict): + path = os.path.join(CONTRACT_PATH, 'opcodes', 'chain_id.tz') + originate(client, session, path, 'Unit', 0) + client.call('bootstrap2', "chain_id", []) + client.bake('bootstrap5', BAKE_ARGS) + + def test_chain_id_authentication_origination(self, client: Client, session): + path = os.path.join( + CONTRACT_PATH, 'mini_scenarios', 'authentication.tz' + ) + pubkey = IDENTITIES['bootstrap1']['public'] + originate(client, session, path, f'Pair 0 "{pubkey}"', 1000) + client.bake('bootstrap5', BAKE_ARGS) + + def test_chain_id_authentication_first_run( + self, client: Client, session: dict + ): + destination = IDENTITIES['bootstrap2']['identity'] + operation = ( + '{DROP; NIL operation; ' + + f'PUSH address "{destination}"; ' + + 'CONTRACT unit; ASSERT_SOME; PUSH mutez 1000; UNIT; ' + + 'TRANSFER_TOKENS; CONS}' + ) + chain_id = client.rpc('get', 'chains/main/chain_id') + contract_address = session['contract'] + packed = client.pack( + f'Pair (Pair "{chain_id}" "{contract_address}") ' + + f'(Pair {operation} 0)', + 'pair (pair chain_id address)' + + '(pair (lambda unit (list operation)) nat)', + ) + signature = client.sign_bytes_of_string(packed, "bootstrap1") + client.call( + 'bootstrap2', + 'authentication', + ['--arg', f'Pair {operation} \"{signature}\"'], + ) + client.bake('bootstrap5', BAKE_ARGS) + + +@pytest.mark.contract +class TestBigMapToSelf: + def test_big_map_to_self_origination(self, client: Client, session: dict): + path = os.path.join(CONTRACT_PATH, 'opcodes', 'big_map_to_self.tz') + originate(client, session, path, '{}', 0) + client.bake('bootstrap5', BAKE_ARGS) + + def test_big_map_to_self_transfer(self, client: Client): + client.call('bootstrap2', "big_map_to_self", []) + client.bake('bootstrap5', BAKE_ARGS) + + client.transfer(0, 'bootstrap2', "big_map_to_self", []) + client.bake('bootstrap5', BAKE_ARGS) + + +@pytest.mark.contract +class TestNonRegression: + """Test contract-related non-regressions""" + + def test_issue_242_originate(self, client: Client, session: dict): + path = os.path.join(CONTRACT_PATH, 'non_regression', 'bug_262.tz') + originate(client, session, path, 'Unit', 1) + + def test_issue_242_assert_balance(self, client: Client): + assert client.get_balance('bug_262') == 1 + + +@pytest.mark.contract +class TestMiniScenarios: + """Test mini scenarios""" + + # replay.tz related tests + def test_replay_originate(self, client: Client, session: dict): + path = os.path.join(CONTRACT_PATH, 'mini_scenarios', 'replay.tz') + originate(client, session, path, 'Unit', 0) + + def test_replay_transfer_fail(self, client: Client): + with utils.assert_run_failure("Internal operation replay attempt"): + client.transfer(10, "bootstrap1", "replay", []) + + # create_contract.tz related tests + def test_create_contract_originate(self, client: Client, session: dict): + path = os.path.join( + CONTRACT_PATH, 'mini_scenarios', 'create_contract.tz' + ) + originate(client, session, path, 'Unit', 1000) + + def test_create_contract_balance(self, client: Client): + assert client.get_balance('create_contract') == 1000 + + def test_create_contract_perform_creation(self, client: Client): + transfer_result = client.transfer( + 0, + "bootstrap1", + "create_contract", + ['-arg', 'None', '--burn-cap', '10'], + ) + client.bake('bootstrap5', BAKE_ARGS) + pattern = r"New contract (\w*) originated" + match = re.search(pattern, transfer_result.client_output) + assert match is not None + kt_1 = match.groups()[0] + assert client.get_storage(kt_1) == '"abcdefg"' + assert client.get_balance(kt_1) == 100 + assert client.get_balance('create_contract') == 900 + + # Originates a contract that when called, creates a contract with a + # rootname annotation. Such annotations comes in two flavors, thus the + # parameterization. Then calls the first contract and verifies the + # existence and type of the root entrypoint of the create contract. + @pytest.mark.parametrize( + "contract", + [ + 'create_contract_rootname.tz', + 'create_contract_rootname_alt.tz', + ], + ) + def test_create_contract_rootname_originate( + self, client: Client, session: dict, contract + ): + path = os.path.join(CONTRACT_PATH, 'opcodes', contract) + origination_res = originate(client, session, path, 'None', 1000) + + transfer_result = client.transfer( + 0, + "bootstrap1", + origination_res.contract, + ['-arg', 'Unit', '--burn-cap', '10'], + ) + client.bake('bootstrap5', BAKE_ARGS) + + pattern = r"New contract (\w*) originated" + match = re.search(pattern, transfer_result.client_output) + assert match is not None + kt_1 = match.groups()[0] + + entrypoint_type = client.get_contract_entrypoint_type( + 'root', kt_1 + ).entrypoint_type + + assert entrypoint_type == 'unit', ( + 'the entrypoint my_root of the originated contract should exist' + 'with type unit' + ) + + # default_account.tz related tests + def test_default_account_originate(self, client: Client, session: dict): + path = os.path.join( + CONTRACT_PATH, 'mini_scenarios', 'default_account.tz' + ) + originate(client, session, path, 'Unit', 1000) + + def test_default_account_transfer_then_bake(self, client: Client): + tz1 = IDENTITIES['bootstrap4']['identity'] + client.transfer( + 0, + "bootstrap1", + "default_account", + ['-arg', f'"{tz1}"', '--burn-cap', '10'], + ) + client.bake('bootstrap5', BAKE_ARGS) + account = 'tz1SuakBpFdG9b4twyfrSMqZzruxhpMeSrE5' + client.transfer( + 0, + "bootstrap1", + "default_account", + ['-arg', f'"{account}"', '--burn-cap', '10'], + ) + client.bake('bootstrap5', BAKE_ARGS) + assert client.get_balance(account) == 100 + + # Test bytes, SHA252, CHECK_SIGNATURE + def test_reveal_signed_preimage_originate( + self, client: Client, session: dict + ): + path = os.path.join( + CONTRACT_PATH, 'mini_scenarios', 'reveal_signed_preimage.tz' + ) + byt = ( + '0x9995c2ef7bcc7ae3bd15bdd9b02' + + 'dc6e877c27b26732340d641a4cbc6524813bb' + ) + sign = 'p2pk66uq221795tFxT7jfNmXtBMdjMf6RAaxRTwv1dbuSHbH6yfqGwz' + storage = f'(Pair {byt} "{sign}")' + originate(client, session, path, storage, 1000) + + def test_wrong_preimage(self, client: Client): + byt = ( + '0x050100000027566f756c657a2d766f75732' + + '0636f75636865722061766563206d6f692c20636520736f6972' + ) + sign = ( + 'p2sigvgDSBnN1bUsfwyMvqpJA1cFhE5s5oi7SetJ' + + 'VQ6LJsbFrU2idPvnvwJhf5v9DhM9ZTX1euS9DgWozVw6BTHiK9VcQVpAU8' + ) + arg = f'(Pair {byt} "{sign}")' + + # We check failure of ASSERT_CMPEQ in the script. + with utils.assert_run_failure("At line 8 characters 9 to 21"): + client.transfer( + 0, + "bootstrap1", + "reveal_signed_preimage", + ['-arg', arg, '--burn-cap', '10'], + ) + + def test_wrong_signature(self, client: Client): + byt = ( + '0x050100000027566f756c657a2d766f757320636' + + 'f75636865722061766563206d6f692c20636520736f6972203f' + ) + sign = ( + 'p2sigvgDSBnN1bUsfwyMvqpJA1cFhE5s5oi7SetJVQ6' + + 'LJsbFrU2idPvnvwJhf5v9DhM9ZTX1euS9DgWozVw6BTHiK9VcQVpAU8' + ) + arg = f'(Pair {byt} "{sign}")' + + # We check failure of CHECK_SIGNATURE ; ASSERT in the script. + with utils.assert_run_failure("At line 15 characters 9 to 15"): + client.transfer( + 0, + "bootstrap1", + "reveal_signed_preimage", + ['-arg', arg, '--burn-cap', '10'], + ) + + def test_good_preimage_and_signature(self, client: Client): + byt = ( + '0x050100000027566f756c657a2d766f757320636f7563' + + '6865722061766563206d6f692c20636520736f6972203f' + ) + sign = ( + 'p2sigsceCzcDw2AeYDzUonj4JT341WC9Px4wdhHBxbZcG1F' + + 'hfqFVuG7f2fGCzrEHSAZgrsrQWpxduDPk9qZRgrpzwJnSHC3gZJ' + ) + arg = f'(Pair {byt} "{sign}")' + client.transfer( + 0, + "bootstrap1", + "reveal_signed_preimage", + ['-arg', arg, '--burn-cap', '10'], + ) + client.bake('bootstrap5', BAKE_ARGS) + + # Test vote_for_delegate + def test_vote_for_delegate_originate(self, client: Client, session: dict): + b_3 = IDENTITIES['bootstrap3']['identity'] + b_4 = IDENTITIES['bootstrap4']['identity'] + path = os.path.join( + CONTRACT_PATH, 'mini_scenarios', 'vote_for_delegate.tz' + ) + storage = f'''(Pair (Pair "{b_3}" None) (Pair "{b_4}" None))''' + originate(client, session, path, storage, 1000) + assert client.get_delegate('vote_for_delegate').delegate is None + + def test_vote_for_delegate_wrong_identity1(self, client: Client): + # We check failure of CHECK_SIGNATURE ; ASSERT in the script. + with utils.assert_run_failure("At line 15 characters 57 to 61"): + client.transfer( + 0, + "bootstrap1", + "vote_for_delegate", + ['-arg', 'None', '--burn-cap', '10'], + ) + + def test_vote_for_delegate_wrong_identity2(self, client: Client): + # We check failure of CHECK_SIGNATURE ; ASSERT in the script. + with utils.assert_run_failure("At line 15 characters 57 to 61"): + client.transfer( + 0, + "bootstrap2", + "vote_for_delegate", + ['-arg', 'None', '--burn-cap', '10'], + ) + + def test_vote_for_delegate_b3_vote_for_b5(self, client: Client): + b_5 = IDENTITIES['bootstrap5']['identity'] + client.transfer( + 0, + "bootstrap3", + "vote_for_delegate", + ['-arg', f'(Some "{b_5}")', '--burn-cap', '10'], + ) + client.bake('bootstrap5', BAKE_ARGS) + storage = client.get_storage('vote_for_delegate') + assert re.search(b_5, storage) + + def test_vote_for_delegate_still_no_delegate1(self, client: Client): + assert client.get_delegate('vote_for_delegate').delegate is None + + def test_vote_for_delegate_b4_vote_for_b2(self, client: Client): + b_2 = IDENTITIES['bootstrap2']['identity'] + client.transfer( + 0, + "bootstrap4", + "vote_for_delegate", + ['-arg', f'(Some "{b_2}")', '--burn-cap', '10'], + ) + client.bake('bootstrap5', BAKE_ARGS) + storage = client.get_storage('vote_for_delegate') + assert re.search(b_2, storage) + + def test_vote_for_delegate_still_no_delegate2(self, client: Client): + assert client.get_delegate('vote_for_delegate').delegate is None + + def test_vote_for_delegate_b4_vote_for_b5(self, client: Client): + b_5 = IDENTITIES['bootstrap5']['identity'] + client.transfer( + 0, + "bootstrap4", + "vote_for_delegate", + ['-arg', f'(Some "{b_5}")', '--burn-cap', '10'], + ) + client.bake('bootstrap5', BAKE_ARGS) + storage = client.get_storage('vote_for_delegate') + assert re.search(b_5, storage) + + def test_vote_for_delegate_has_delegate(self, client: Client): + b_5 = IDENTITIES['bootstrap5']['identity'] + result = client.get_delegate('vote_for_delegate') + assert result.delegate == b_5 + + def test_multiple_entrypoints_counter(self, session: dict, client: Client): + path = os.path.join( + CONTRACT_PATH, 'mini_scenarios', 'multiple_entrypoints_counter.tz' + ) + + storage = 'None' + + # originate contract + originate(client, session, path, storage, 0) + client.bake('bootstrap5', BAKE_ARGS) + + # call contract: creates the internal contract and calls it. + client.transfer( + 0, + 'bootstrap1', + 'multiple_entrypoints_counter', + ['--burn-cap', '10'], + ) + client.bake('bootstrap5', BAKE_ARGS) + assert client.get_storage('multiple_entrypoints_counter') == 'None', ( + "The storage of the multiple_entrypoints_counter contract" + " should be None" + ) + + # Test CONTRACT with/without entrypoint annotation on literal address + # parameters with/without entrypoint annotation + def test_originate_simple_entrypoints(self, session: dict, client: Client): + """originates the contract simple_entrypoints.tz + with entrypoint %A of type unit used in + test_simple_entrypoints""" + + contract_target = os.path.join( + CONTRACT_PATH, 'entrypoints', 'simple_entrypoints.tz' + ) + originate(client, session, contract_target, 'Unit', 0) + client.bake('bootstrap5', BAKE_ARGS) + + @pytest.mark.parametrize( + 'contract_annotation, contract_type, param, expected_storage', + [ + # tests passing adr to CONTRACT %A unit + # where adr has an entrypoint %A of type unit, is allowed. + ('%A', 'unit', '"{adr}"', '(Some "{adr}%A")'), + ('%B', 'string', '"{adr}"', '(Some "{adr}%B")'), + ('%C', 'nat', '"{adr}"', '(Some "{adr}%C")'), + # tests passing adr%A to CONTRACT %A unit: redundant specification + # of entrypoint not allowed so CONTRACT returns None + ('%A', 'unit', '"{adr}%A"', 'None'), + ('%A', 'unit', '"{adr}%B"', 'None'), + ('%A', 'unit', '"{adr}%D"', 'None'), + ('%A', 'unit', '"{adr}%A"', 'None'), + ('%B', 'unit', '"{adr}%A"', 'None'), + ('%D', 'unit', '"{adr}%A"', 'None'), + # tests passing adr%A to CONTRACT unit: + # where adr has an entrypoint %A of type unit, is allowed. + ('', 'unit', '"{adr}%A"', '(Some "{adr}%A")'), + ('', 'string', '"{adr}%B"', '(Some "{adr}%B")'), + ('', 'nat', '"{adr}%C"', '(Some "{adr}%C")'), + # tests passing adr%B to CONTRACT unit: + # as entrypoint %B of simple_entrypoints.tz has type string, + # CONTRACT will return None. + ('', 'unit', '"{adr}%B"', 'None'), + # tests passing adr%D to CONTRACT unit: + # as entrypoint %D does not exist in simple_entrypoints.tz, + # CONTRACT will return None. + ('', 'unit', '"{adr}%D"', 'None'), + # tests passing adr to CONTRACT unit: + # as adr does not have type unit, CONTRACT returns None. + ('', 'unit', '"{adr}"', 'None'), + # entrypoint that does not exist + ('%D', 'unit', '"{adr}"', 'None'), + # ill-typed entrypoints + ('%A', 'int', '"{adr}"', 'None'), + ('%B', 'unit', '"{adr}"', 'None'), + ('%C', 'int', '"{adr}"', 'None'), + ], + ) + def test_simple_entrypoints( + self, + session, + client, + contract_annotation, + contract_type, + param, + expected_storage, + ): + contract = f'''parameter address; +storage (option address); +code {{ + CAR; + CONTRACT {contract_annotation} {contract_type}; + IF_SOME {{ ADDRESS; SOME }} {{ NONE address; }}; + NIL operation; + PAIR + }};''' + + param = param.format(adr=session['contract']) + expected_storage = expected_storage.format(adr=session['contract']) + run_script_res = client.run_script(contract, 'None', param, file=False) + assert run_script_res.storage == expected_storage + + +@pytest.mark.contract +class TestComparables: + def test_comparable_unit(self, client): + client.typecheck_data('{}', '(set unit)') + client.typecheck_data('{Unit}', '(set unit)') + + def test_comparable_options(self, client): + client.typecheck_data('{}', '(set (option nat))') + client.typecheck_data('{None; Some 1; Some 2}', '(set (option int))') + utils.assert_typecheck_data_failure( + client, '{Some "foo"; Some "bar"}', '(set (option string))' + ) + utils.assert_typecheck_data_failure( + client, '{Some Unit; None}', '(set (option unit))' + ) + + def test_comparable_unions(self, client): + client.typecheck_data('{}', '(set (or unit bool))') + client.typecheck_data( + '{Left 3; Left 4; Right "bar"; Right "foo"}', + '(set (or nat string))', + ) + utils.assert_typecheck_data_failure( + client, '{Left 2; Left 1}', '(set (or mutez unit))' + ) + utils.assert_typecheck_data_failure( + client, '{Right True; Right False}', '(set (or unit bool))' + ) + utils.assert_typecheck_data_failure( + client, '{Right 0; Left 1}', '(set (or nat nat))' + ) + + def test_comparable_pair(self, client: Client): + # tests that comb pairs are comparable and that the order is the + # expected one + client.typecheck_data('{}', '(set (pair nat string))') + client.typecheck_data('{Pair 0 "foo"}', '(set (pair nat string))') + client.typecheck_data( + '{Pair 0 "foo"; Pair 1 "bar"}', '(set (pair nat string))' + ) + client.typecheck_data( + '{Pair 0 "bar"; Pair 0 "foo"; \ + Pair 1 "bar"; Pair 1 "foo"}', + '(set (pair nat string))', + ) + client.typecheck_data('{}', '(set (pair nat (pair string bytes)))') + + client.typecheck_data('{}', '(map (pair nat string) unit)') + client.typecheck_data( + '{Elt (Pair 0 "foo") Unit}', '(map (pair nat string) unit)' + ) + client.typecheck_data( + '{Elt (Pair 0 "foo") Unit; \ + Elt (Pair 1 "bar") Unit}', + '(map (pair nat string) unit)', + ) + client.typecheck_data( + '{Elt (Pair 0 "bar") Unit; \ + Elt (Pair 0 "foo") Unit; \ + Elt (Pair 1 "bar") Unit; \ + Elt (Pair 1 "foo") Unit}', + '(map (pair nat string) unit)', + ) + client.typecheck_data('{}', '(map (pair nat (pair string bytes)) unit)') + + client.typecheck_data('{}', '(big_map (pair nat string) unit)') + client.typecheck_data( + '{Elt (Pair 0 "foo") Unit}', '(big_map (pair nat string) unit)' + ) + client.typecheck_data( + '{Elt (Pair 0 "foo") Unit; \ + Elt (Pair 1 "bar") Unit}', + '(big_map (pair nat string) unit)', + ) + client.typecheck_data( + '{Elt (Pair 0 "bar") Unit; \ + Elt (Pair 0 "foo") Unit; \ + Elt (Pair 1 "bar") Unit; \ + Elt (Pair 1 "foo") Unit}', + '(big_map (pair nat string) unit)', + ) + client.typecheck_data( + '{}', '(big_map (pair nat (pair string bytes)) unit)' + ) + client.typecheck_data('{}', '(set (pair (pair nat nat) nat))') + client.typecheck_data( + '{}', + '(set (pair (pair int nat) \ + (pair bool bytes)))', + ) + + def test_order_of_pairs(self, client: Client): + # tests that badly-ordered set literals are rejected + utils.assert_typecheck_data_failure( + client, '{Pair 0 "foo"; Pair 0 "bar"}', '(set (pair nat string))' + ) + utils.assert_typecheck_data_failure( + client, '{Pair 1 "bar"; Pair 0 "foo"}', '(set (pair nat string))' + ) + + def test_comparable_chain_id(self, client): + client.typecheck_data('{}', '(set chain_id)') + chain1 = client.rpc('get', 'chains/main/chain_id') + chain2 = 'NetXZVhNXbDTx5M' + utils.assert_typecheck_data_failure( + client, + '{"' + f'{chain1}' + '"; "' + f'{chain2}' + '"}', + '(set chain_id)', + ) + client.typecheck_data( + '{"' + f'{chain2}' + '"; "' + f'{chain1}' + '"}', '(set chain_id)' + ) + + def test_comparable_signature(self, client): + client.typecheck_data('{}', '(set signature)') + packed = client.pack('Unit', 'unit') + sig1 = client.sign_bytes_of_string(packed, "bootstrap1") + sig2 = client.sign_bytes_of_string(packed, "bootstrap2") + utils.assert_typecheck_data_failure( + client, + '{"' + f'{sig1}' + '"; "' + f'{sig2}' + '"}', + '(set signature)', + ) + client.typecheck_data( + '{"' + f'{sig2}' + '"; "' + f'{sig1}' + '"}', '(set signature)' + ) + + def test_comparable_key(self, client): + pubkey1 = IDENTITIES['bootstrap1']['public'] + pubkey2 = IDENTITIES['bootstrap2']['public'] + client.typecheck_data('{}', '(set key)') + utils.assert_typecheck_data_failure( + client, + '{"' + f'{pubkey1}' + '"; "' + f'{pubkey2}' + '"}', + '(set key)', + ) + client.typecheck_data( + '{"' + f'{pubkey2}' + '"; "' + f'{pubkey1}' + '"}', '(set key)' + ) + + def test_comparable_key_different_schemes(self, client): + client.gen_key('sk1', ['--sig', 'ed25519']) + key1 = client.show_address('sk1').public_key + + client.gen_key('sk2', ['--sig', 'secp256k1']) + key2 = client.show_address('sk2').public_key + + client.gen_key('sk3', ['--sig', 'p256']) + key3 = client.show_address('sk3').public_key + + # Three public keys of the three different signature schemes, ordered + client.typecheck_data( + '{"' + key1 + '"; "' + key2 + '"; "' + key3 + '"}', '(set key)' + ) + + # Test all orderings that do not respect the comparable order + utils.assert_typecheck_data_failure( + client, + '{"' + key1 + '"; "' + key3 + '"; "' + key2 + '"}', + '(set key)', + ) + + utils.assert_typecheck_data_failure( + client, + '{"' + key2 + '"; "' + key1 + '"; "' + key3 + '"}', + '(set key)', + ) + + utils.assert_typecheck_data_failure( + client, + '{"' + key2 + '"; "' + key3 + '"; "' + key1 + '"}', + '(set key)', + ) + + utils.assert_typecheck_data_failure( + client, + '{"' + key3 + '"; "' + key1 + '"; "' + key2 + '"}', + '(set key)', + ) + + utils.assert_typecheck_data_failure( + client, + '{"' + key3 + '"; "' + key2 + '"; "' + key1 + '"}', + '(set key)', + ) + + +@pytest.mark.contract +class TestTypecheckingErrors: + def test_big_map_arity_error(self, client: Client): + error_pattern = ( + 'primitive EMPTY_BIG_MAP expects 2 arguments but is given 1.' + ) + with utils.assert_run_failure(error_pattern): + client.typecheck( + os.path.join(CONTRACT_PATH, 'ill_typed', 'big_map_arity.tz') + ) + + +BAD_ANNOT_TEST = ''' +parameter bytes; +storage (option (lambda unit unit)); +code { CAR; UNPACK (lambda unit unit); NIL operation; PAIR} +''' + + +@pytest.mark.contract +class TestBadAnnotation: + def test_write_contract_bad_annot(self, tmpdir, session: dict): + name = 'bad_annot.tz' + contract = f'{tmpdir}/{name}' + script = BAD_ANNOT_TEST + with open(contract, 'w') as contract_file: + contract_file.write(script) + session[name] = contract + + def test_bad_annotation(self, client: Client, session: dict): + name = 'bad_annot.tz' + contract = session[name] + + # This was produced by running "tezos-client hash data '{ UNIT + # ; PAIR ; CAR %faa }' of type 'lambda unit unit'" and + # replacing the two last bytes (that correspond to the two + # 'a's at the end of the annotation) by the 0xff byte which is + # not a valid UTF8-encoding of a string + parameter = '0x05020000000e034f03420416000000042566ffff' + + res = client.run_script(contract, 'None', parameter) + assert res.storage == 'None' + + +@pytest.mark.contract +class TestOrderInTopLevelDoesNotMatter: + @pytest.fixture + def contract_splitted_in_top_level_elements(self): + return [ + "parameter nat", + "storage unit", + "code { CDR; NIL operation; PAIR }", + ] + + def test_shuffle( + self, client: Client, contract_splitted_in_top_level_elements + ): + """ + Test that the storage, code, and parameter sections can appear in any + order in a contract script. + """ + for shuffled_list in itertools.permutations( + contract_splitted_in_top_level_elements + ): + contract = ";\n".join(shuffled_list) + client.typecheck(contract, file=False) + + +@pytest.mark.contract +@pytest.mark.regression +class TestSelfAddressTransfer: + def test_self_address_originate_sender( + self, client_regtest_scrubbed, session + ): + client = client_regtest_scrubbed + path = os.path.join( + CONTRACT_PATH, 'mini_scenarios', 'self_address_sender.tz' + ) + originate(client, session, path, 'Unit', 0) + + def test_self_address_originate_receiver( + self, client_regtest_scrubbed, session + ): + client = client_regtest_scrubbed + path = os.path.join( + CONTRACT_PATH, 'mini_scenarios', 'self_address_receiver.tz' + ) + originate(client, session, path, 'Unit', 0) + session['receiver_address'] = session['contract'] + + def test_send_self_address(self, client_regtest_scrubbed, session): + client = client_regtest_scrubbed + receiver_address = session['receiver_address'] + client.transfer( + 0, + 'bootstrap2', + 'self_address_sender', + ['--arg', f'"{receiver_address}"', '--burn-cap', '2'], + ) + client.bake('bootstrap5', BAKE_ARGS) + + +@pytest.mark.contract +@pytest.mark.regression +class TestNormalize: + """Regression tests for the "normalize data" command.""" + + modes = [None, 'Readable', 'Optimized', 'Optimized_legacy'] + + @pytest.mark.parametrize('mode', modes) + def test_normalize_unparsing_mode(self, client_regtest_scrubbed, mode): + client = client_regtest_scrubbed + input_data = ( + '{Pair 0 3 6 9; Pair 1 (Pair 4 (Pair 7 10)); {2; 5; 8; 11}}' + ) + input_type = 'list (pair nat nat nat nat)' + client.normalize(input_data, input_type, mode=mode) + + def test_normalize_legacy_flag(self, client_regtest_scrubbed): + client = client_regtest_scrubbed + input_data = '{Elt %a 0 1}' + input_type = 'map nat nat' + client.normalize(input_data, input_type, legacy=True) + error_pattern = 'unexpected annotation.' + with utils.assert_run_failure(error_pattern): + client.normalize(input_data, input_type, legacy=False) + + @pytest.mark.parametrize('mode', modes) + def test_normalize_script(self, client_regtest_scrubbed, mode): + client = client_regtest_scrubbed + path = os.path.join(CONTRACT_PATH, 'opcodes', 'comb-literals.tz') + client.normalize_script(path, mode=mode) + + types = [ + 'nat', + 'list nat', + 'pair nat int', + 'list (pair nat int)', + 'pair nat int bool', + 'list (pair nat int bool)', + 'pair nat int bool bytes', + 'list (pair nat int bool bytes)', + ] + + @pytest.mark.parametrize('typ', types) + def test_normalize_type(self, client_regtest_scrubbed, typ): + client = client_regtest_scrubbed + client.normalize_type(typ) diff --git a/tests_python/tests_009/test_contract_annotations.py b/tests_python/tests_009/test_contract_annotations.py new file mode 100644 index 0000000000000000000000000000000000000000..c34dcc016ee148b71e324b5ea1a35bb30b9b5b09 --- /dev/null +++ b/tests_python/tests_009/test_contract_annotations.py @@ -0,0 +1,88 @@ +import pytest +from tools.utils import assert_typecheck_data_failure, assert_typecheck_failure +from client.client import Client + + +@pytest.mark.slow +@pytest.mark.contract +class TestAnnotations: + """Tests of Michelson annotations.""" + + def test_annotation_length_success(self, client: Client): + client.typecheck_data('3', f"(int :{'a' * 254})") + + def test_annotation_length_failure(self, client: Client): + assert_typecheck_data_failure( + client, + '3', + f"(int :{'a' * 255})", + r'annotation exceeded maximum length \(255 chars\)', + ) + + def test_field_annotation_in_type_alphabetic(self, client): + client.typecheck_data('Pair 0 0', 'pair (nat %x) (int %y)') + + def test_field_annotation_in_type_numeral(self, client): + client.typecheck_data('Pair 0 0', 'pair (nat %1) (int %2)') + + def test_field_annotation_in_type_invalid_character(self, client): + assert_typecheck_data_failure( + client, + 'Pair 0 0', + 'pair (nat %.) (int %.)', + 'unexpected annotation', + ) + + def test_field_annotation_in_instruction_alphabetic(self, client): + client.typecheck_data( + '{ CAR %x }', 'lambda (pair (nat %x) (int %y)) nat' + ) + + def test_field_annotation_in_instruction_numeral(self, client): + client.typecheck_data( + '{ CAR %1 }', 'lambda (pair (nat %1) (int %2)) nat' + ) + + def test_field_annotation_in_instruction_invalid_character(self, client): + assert_typecheck_data_failure( + client, + '{ CAR %. }', + 'lambda (pair (nat %.) (int %.)) nat', + 'unexpected annotation', + ) + + def test_field_annotation_in_root_alphabetic(self, client): + client.typecheck( + 'parameter %r unit; storage unit; code {FAILWITH}', file=False + ) + + def test_field_annotation_in_root_numeral(self, client): + client.typecheck( + 'parameter %1 unit; storage unit; code {FAILWITH}', file=False + ) + + def test_field_annotation_in_root_invalid_character(self, client): + assert_typecheck_failure( + client, + 'parameter %. unit; storage unit; code {FAILWITH}', + 'unexpected annotation', + file=False, + ) + + def test_field_annotation_in_root_type_alphabetic(self, client): + client.typecheck( + 'parameter (unit %r); storage unit; code {FAILWITH}', file=False + ) + + def test_field_annotation_in_root_type_numeral(self, client): + client.typecheck( + 'parameter (unit %1); storage unit; code {FAILWITH}', file=False + ) + + def test_field_annotation_in_root_type_invalid_character(self, client): + assert_typecheck_failure( + client, + 'parameter (unit %.); storage unit; code {FAILWITH}', + 'unexpected annotation', + file=False, + ) diff --git a/tests_python/tests_009/test_contract_baker.py b/tests_python/tests_009/test_contract_baker.py new file mode 100644 index 0000000000000000000000000000000000000000..862a2f339c7db3101d0547c9cb7f0df6379c9ffb --- /dev/null +++ b/tests_python/tests_009/test_contract_baker.py @@ -0,0 +1,55 @@ +import os +import pytest +from tools import utils +from client.client import Client +from . import contract_paths + + +BAKE_ARGS = ['--minimal-timestamp'] + + +@pytest.mark.contract +@pytest.mark.baker +@pytest.mark.incremental +class TestOriginationCall: + """Test a simple contract origination and call""" + + def test_originate(self, client: Client, session: dict): + initial_storage = 'Unit' + contract = os.path.join( + contract_paths.OPCODES_CONTRACT_PATH, 'transfer_tokens.tz' + ) + args = ['--init', initial_storage, '--burn-cap', '0.400'] + origination = client.originate( + 'foobar', 1000, 'bootstrap1', contract, args + ) + session['contract'] = origination.contract + client.bake('bootstrap5', BAKE_ARGS) + + # Unsolved mystery: + # client.wait_for_inclusion(origination.operation_hash) + # fails sometimes with tezos-client crashing. Maybe caused with + # subprocess captured of forked process output? + # + # Safer to poll with `check_block_contain_operations` + assert utils.check_block_contains_operations( + client, [origination.operation_hash] + ) + + def test_call(self, client: Client, session: dict): + contract = session['contract'] + bootstrap3 = '"tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU"' + transfer = client.call('bootstrap2', contract, ['--arg', bootstrap3]) + client.bake('bootstrap5', BAKE_ARGS) + assert utils.check_block_contains_operations( + client, [transfer.operation_hash] + ) + + def test_balance(self, client: Client): + assert client.get_balance("bootstrap3") == 4000100 + + def test_query_storage(self, client: Client, session: dict): + contract = session['contract'] + url = f'/chains/main/blocks/head/context/contracts/{contract}/storage' + res = client.rpc('get', url) + assert res['prim'] == 'Unit' diff --git a/tests_python/tests_009/test_contract_bls12_381.py b/tests_python/tests_009/test_contract_bls12_381.py new file mode 100644 index 0000000000000000000000000000000000000000..67a6569e4e7f5bc46d64c4cbb9d8cf2d39bdc7a8 --- /dev/null +++ b/tests_python/tests_009/test_contract_bls12_381.py @@ -0,0 +1,316 @@ +from os import path +import random +from hashlib import blake2b +import pytest + +from tools.bls12_381 import G1, G2, Fr, pairing_check +from tools.utils import assert_run_failure +from .contract_paths import MINI_SCENARIOS_CONTRACT_PATH, OPCODES_CONTRACT_PATH + +BAKE_ARGS = ['--minimal-timestamp'] + + +def check_contract(client, contract_name, arg, expected_storage): + contract_path = path.join(OPCODES_CONTRACT_PATH, f'{contract_name}.tz') + result = client.run_script(contract_path, 'None', arg) + assert result.storage == f'(Some {expected_storage})' + + +def check_contract_binop(client, contract_name, arg0, arg1, expected_storage): + check_contract( + client, contract_name, f'Pair {arg0} {arg1}', expected_storage + ) + + +# prefix a type name with 'bls12_381_' +def bls(tname): + return f'bls12_381_{tname}' + + +# Store +def check_store(client, cls, arg): + arg = cls.to_hex(arg) + check_contract(client, f'store_{bls(cls.name)}', arg, arg) + + +# Add +def check_add(client, cls, xxx, yyy): + check_contract_binop( + client, + f'add_{bls(cls.name)}', + cls.to_hex(xxx), + cls.to_hex(yyy), + cls.to_hex(cls.add(xxx, yyy)), + ) + + +# Mul +def check_mul(client, cls, xxx, yyy): + check_contract_binop( + client, + f'mul_{bls(cls.name)}', + cls.to_hex(xxx), + Fr.to_hex(yyy), + cls.to_hex(cls.mul(xxx, yyy)), + ) + + +# Neg +def check_neg(client, cls, arg): + res = cls.to_hex(cls.neg(arg)) + arg = cls.to_hex(arg) + check_contract(client, f'neg_{bls(cls.name)}', arg, res) + + +# Pairing Check +def check_pairing_check(client, args): + res = pairing_check(args) + args = [(G1.to_hex(g1), G2.to_hex(g2)) for g1, g2 in args] + args = [f'Pair {g1} {g2}' for g1, g2 in args] + args = f'{{ {"; ".join(args)} }}' + check_contract(client, 'pairing_check', args, res) + + +# Setting this higher makes things rather slow +RANDOM_ITERATIONS = range(10) + +STORE_CLASSES = [G1, G2, Fr] +CURVES = [G1, G2] +ADD_CLASSES = [G1, G2, Fr] +MUL_CLASSES = [G1, G2, Fr] +NEG_CLASSES = [G1, G2, Fr] + + +@pytest.mark.contract +@pytest.mark.regression +class TestBls12_381: + + # Fix the random seed to ensure reproducibility + h = blake2b() + h.update(b'seed') + gen = random.Random() + gen.seed(bytes.fromhex(h.hexdigest())) + + # Store + @pytest.mark.parametrize("cls", STORE_CLASSES) + def test_store_zero(self, client_regtest, cls): + check_store(client_regtest, cls, cls.zero) + + @pytest.mark.parametrize("cls", STORE_CLASSES) + def test_store_one(self, client_regtest, cls): + check_store(client_regtest, cls, cls.one) + + @pytest.mark.parametrize("cls", STORE_CLASSES) + def test_store_random(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_store(client_regtest, cls, cls.random(self.gen)) + + # Add + @pytest.mark.parametrize("cls", ADD_CLASSES) + def test_add_zero_zero(self, client_regtest, cls): + check_add(client_regtest, cls, cls.zero, cls.zero) + + @pytest.mark.parametrize("cls", ADD_CLASSES) + def test_add_zero_one(self, client_regtest, cls): + check_add(client_regtest, cls, cls.zero, cls.one) + + @pytest.mark.parametrize("cls", ADD_CLASSES) + def test_add_zero_random(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_add(client_regtest, cls, cls.zero, cls.random(self.gen)) + + @pytest.mark.parametrize("cls", ADD_CLASSES) + def test_add_one_zero(self, client_regtest, cls): + check_add(client_regtest, cls, cls.one, cls.zero) + + @pytest.mark.parametrize("cls", ADD_CLASSES) + def test_add_one_one(self, client_regtest, cls): + check_add(client_regtest, cls, cls.one, cls.one) + + @pytest.mark.parametrize("cls", ADD_CLASSES) + def test_add_one_random(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_add(client_regtest, cls, cls.one, cls.random(self.gen)) + + @pytest.mark.parametrize("cls", ADD_CLASSES) + def test_add_random_zero(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_add(client_regtest, cls, cls.random(self.gen), cls.zero) + + @pytest.mark.parametrize("cls", ADD_CLASSES) + def test_add_random_one(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_add(client_regtest, cls, cls.random(self.gen), cls.one) + + @pytest.mark.parametrize("cls", ADD_CLASSES) + def test_add_random_random(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_add( + client_regtest, cls, cls.random(self.gen), cls.random(self.gen) + ) + + # Mul + @pytest.mark.parametrize("cls", MUL_CLASSES) + def test_mul_zero_zero(self, client_regtest, cls): + check_mul(client_regtest, cls, cls.zero, Fr.zero) + + @pytest.mark.parametrize("cls", MUL_CLASSES) + def test_mul_zero_one(self, client_regtest, cls): + check_mul(client_regtest, cls, cls.zero, Fr.one) + + @pytest.mark.parametrize("cls", MUL_CLASSES) + def test_mul_zero_random(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_mul(client_regtest, cls, cls.zero, Fr.random(self.gen)) + + @pytest.mark.parametrize("cls", MUL_CLASSES) + def test_mul_one_zero(self, client_regtest, cls): + check_mul(client_regtest, cls, cls.one, Fr.zero) + + @pytest.mark.parametrize("cls", MUL_CLASSES) + def test_mul_one_one(self, client_regtest, cls): + check_mul(client_regtest, cls, cls.one, Fr.one) + + @pytest.mark.parametrize("cls", MUL_CLASSES) + def test_mul_one_random(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_mul(client_regtest, cls, cls.one, Fr.random(self.gen)) + + @pytest.mark.parametrize("cls", MUL_CLASSES) + def test_mul_random_zero(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_mul(client_regtest, cls, cls.random(self.gen), Fr.zero) + + @pytest.mark.parametrize("cls", MUL_CLASSES) + def test_mul_random_one(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_mul(client_regtest, cls, cls.random(self.gen), Fr.one) + + @pytest.mark.parametrize("cls", MUL_CLASSES) + def test_mul_random_random(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_mul( + client_regtest, cls, cls.random(self.gen), Fr.random(self.gen) + ) + + # Neg + @pytest.mark.parametrize("cls", NEG_CLASSES) + def test_neg_zero(self, client_regtest, cls): + check_neg(client_regtest, cls, cls.zero) + + @pytest.mark.parametrize("cls", NEG_CLASSES) + def test_neg_one(self, client_regtest, cls): + check_neg(client_regtest, cls, cls.one) + + @pytest.mark.parametrize("cls", NEG_CLASSES) + def test_neg_random(self, client_regtest, cls): + for _ in RANDOM_ITERATIONS: + check_neg(client_regtest, cls, cls.random(self.gen)) + + # Pairing checks + def test_pairing_nil(self, client_regtest): + check_pairing_check(client_regtest, []) + + def test_pairing_zero_zero(self, client_regtest): + args = [(G1.zero, G2.zero)] + check_pairing_check(client_regtest, args) + + def test_pairing_zero_one(self, client_regtest): + args = [(G1.zero, G2.one)] + check_pairing_check(client_regtest, args) + + def test_pairing_zero_random(self, client_regtest): + for _ in RANDOM_ITERATIONS: + args = [(G1.zero, G2.random(self.gen))] + check_pairing_check(client_regtest, args) + + def test_pairing_one_zero(self, client_regtest): + args = [(G1.one, G2.zero)] + check_pairing_check(client_regtest, args) + + def test_pairing_one_one(self, client_regtest): + args = [(G1.one, G2.one)] + check_pairing_check(client_regtest, args) + + def test_pairing_one_random(self, client_regtest): + for _ in RANDOM_ITERATIONS: + args = [(G1.one, G2.random(self.gen))] + check_pairing_check(client_regtest, args) + + def test_pairing_random_zero(self, client_regtest): + for _ in RANDOM_ITERATIONS: + args = [(G1.random(self.gen), G2.zero)] + check_pairing_check(client_regtest, args) + + def test_pairing_random_one(self, client_regtest): + for _ in RANDOM_ITERATIONS: + args = [(G1.random(self.gen), G2.one)] + check_pairing_check(client_regtest, args) + + def test_pairing_random_random(self, client_regtest): + for _ in RANDOM_ITERATIONS: + args = [(G1.random(self.gen), G2.random(self.gen))] + check_pairing_check(client_regtest, args) + + def test_pairing_neg_g1(self, client_regtest): + for _ in RANDOM_ITERATIONS: + g1_point = G1.random(self.gen) + g2_point = G2.random(self.gen) + args = [(g1_point, g2_point), (G1.neg(g1_point), g2_point)] + check_pairing_check(client_regtest, args) + + def test_pairing_neg_g2(self, client_regtest): + for _ in RANDOM_ITERATIONS: + g1_point = G1.random(self.gen) + g2_point = G2.random(self.gen) + args = [(g1_point, g2_point), (g1_point, G2.neg(g2_point))] + check_pairing_check(client_regtest, args) + + # Pairing Check test based on signature aggregation + def test_signature_aggregation(self, client_regtest): + for _ in RANDOM_ITERATIONS: + sk0 = Fr.random(self.gen) # secret key + pk0 = G2.mul(G2.one, sk0) # public key + # we don't have hash-to-curve on g1, so compute a random point + msg_hash = G1.random(self.gen) # message hash + sig0 = G1.mul(msg_hash, sk0) # signature + args0 = [(msg_hash, pk0), (G1.neg(sig0), G2.one)] + check_pairing_check(client_regtest, args0) + + sk1 = Fr.random(self.gen) # secret key + pk1 = G2.mul(G2.one, sk1) # public key + # we don't have hash-to-curve on g1, so compute a random point + sig1 = G1.mul(msg_hash, sk1) # signature + args1 = [ + (G1.add(msg_hash, msg_hash), G2.add(pk0, pk1)), + (G1.neg(G1.add(sig0, sig1)), G2.add(G2.one, G2.one)), + ] + check_pairing_check(client_regtest, args1) + + def test_groth16(self, client_regtest): + # pylint: disable=line-too-long + # The verifying key, proof, and inputs are generated from + # ZoKrates, modified to use BLS12-381. + # The circuit proves knowledge of a square root of 113569. + + input_x = "0xa1bb010000000000000000000000000000000000000000000000000000000000" # noqa + input_y = "0x0100000000000000000000000000000000000000000000000000000000000000" # noqa + proof_a = "0x0a2841423326ab08f5f406409775e43fa0f9a0b97631fa85d2dd9242507d25059e9cf48b8b98f99a0008671423a148ec106d70637056972ef49fb6f62de2e89ba3682b9972292b6bb4e6f53799a75d2f8001ccfde280d8ac05fc209352236cbd" # noqa + proof_b = "0x0fced939fb1ad733f99669f50a383ef632f6d41dfbde434a6715afd5c7dfbb7bc5835e058ad8b590c7b38dd137d0bd0f0e1540f1b45d8aa626c360e2ea484a116243f7c802034de915db6b18d5303946f676e423cbd6046d37a82208d500625a11c7250ccb953a7ee49d704ad14de4b727733cff7cf06875d8b6444f3c0a8cbf0bd980e539c74bd5b37bb15fe816f23407d269193105fda71adf35fae9309d9d46729fcd4685699097a86f0460a2bc8b16293940cabfdcfe0f27e4107e74e90c" # noqa + proof_c = "0x0a1fb5a144ca3bdfe4ad0f183cf71dd7fdd28cbef4fcd47b5b419f65186703f62ecaaa1255fa21a6ebdd917ab1f9bd9707de7066865e2ff3875e22088619125a0d4088a622ab42224425ef89a5a149ce2db9c8292b62c7e7aaa7e87f3535304b" # noqa + + inputs = f"Pair {input_x} {input_y}" + proof = f"Pair (Pair {proof_a} {proof_b}) {proof_c}" + arg = f"Pair ({inputs}) ({proof})" + + contract = path.join(MINI_SCENARIOS_CONTRACT_PATH, 'groth16.tz') + client_regtest.run_script(contract, 'Unit', arg) + + def test_fr_bytes_parameters_more_than_32_bytes(self, client_regtest): + random_bytes = ( + "0xf7ef66f95c90b2f953eb0555af65f22095d4f54b40ea8c6d" + + "cc2014740e8662c16bb8786723" + ) + contract = path.join(OPCODES_CONTRACT_PATH, 'bls12_381_fr_to_int.tz') + with assert_run_failure(r'error running script'): + client_regtest.run_script(contract, storage='0', inp=random_bytes) diff --git a/tests_python/tests_009/test_contract_macros.py b/tests_python/tests_009/test_contract_macros.py new file mode 100644 index 0000000000000000000000000000000000000000..e8d65dbadbf029b765720bd9a24649825fc22e39 --- /dev/null +++ b/tests_python/tests_009/test_contract_macros.py @@ -0,0 +1,450 @@ +from os import path +import pytest +from tools.utils import ( + assert_run_script_failwith, + assert_transfer_failwith, + init_with_transfer, + bake, + assert_storage_contains, +) +from tools.client_regression import ClientRegression +from client.client import Client +from .contract_paths import MACROS_CONTRACT_PATH, CONTRACT_PATH, all_contracts + + +BAKE_ARGS = ['--minimal-timestamp'] + + +@pytest.mark.contract +class TestContractMacros: + """Tests for contracts using macros that do not require origination.""" + + @pytest.mark.parametrize( + "contract,param,storage,expected", + [ # FORMAT: assert_output contract_file storage input expected_result + # Build list + ('build_list.tz', '{}', '0', '{ 0 }'), + ('build_list.tz', '{}', '3', '{ 0 ; 1 ; 2 ; 3 }'), + ( + 'build_list.tz', + '{}', + '10', + '{ 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 ; 10 }', + ), + # Find maximum int in list -- returns None if not found + ('max_in_list.tz', 'None', '{}', 'None'), + ('max_in_list.tz', 'None', '{ 1 }', '(Some 1)'), + ('max_in_list.tz', 'None', '{ -1 }', '(Some -1)'), + ( + 'max_in_list.tz', + 'None', + '{ 10 ; -1 ; -20 ; 100 ; 0 }', + '(Some 100)', + ), + ( + 'max_in_list.tz', + 'None', + '{ 10 ; -1 ; -20 ; 100 ; 0 }', + '(Some 100)', + ), + ( + 'max_in_list.tz', + 'None', + '{ -10 ; -1 ; -20 ; -100 }', + '(Some -1)', + ), + # Test comparisons on tez { EQ ; GT ; LT ; GE ; LE } + ( + 'compare.tz', + '{}', + '(Pair 1000000 2000000)', + '{ False ; False ; True ; False ; True }', + ), + ( + 'compare.tz', + '{}', + '(Pair 2000000 1000000)', + '{ False ; True ; False ; True ; False }', + ), + ( + 'compare.tz', + '{}', + '(Pair 2370000 2370000)', + '{ True ; False ; False ; True ; True }', + ), + # Test ASSERT + ('assert.tz', 'Unit', 'True', 'Unit'), + # ASSERT_{OP} + ('assert_eq.tz', 'Unit', '(Pair -1 -1)', 'Unit'), + ('assert_eq.tz', 'Unit', '(Pair -1 -1)', 'Unit'), + ('assert_neq.tz', 'Unit', '(Pair 0 -1)', 'Unit'), + ('assert_lt.tz', 'Unit', '(Pair -1 0)', 'Unit'), + ('assert_le.tz', 'Unit', '(Pair 0 0)', 'Unit'), + ('assert_le.tz', 'Unit', '(Pair -1 0)', 'Unit'), + ('assert_gt.tz', 'Unit', '(Pair 0 -1)', 'Unit'), + ('assert_ge.tz', 'Unit', '(Pair 0 0)', 'Unit'), + ('assert_ge.tz', 'Unit', '(Pair 0 -1)', 'Unit'), + # ASSERT_CMP{OP} + ('assert_cmpeq.tz', 'Unit', '(Pair -1 -1)', 'Unit'), + ('assert_cmpneq.tz', 'Unit', '(Pair 0 -1)', 'Unit'), + ('assert_cmplt.tz', 'Unit', '(Pair -1 0)', 'Unit'), + ('assert_cmple.tz', 'Unit', '(Pair -1 0)', 'Unit'), + ('assert_cmple.tz', 'Unit', '(Pair 0 0)', 'Unit'), + ('assert_cmpgt.tz', 'Unit', '(Pair 0 -1)', 'Unit'), + ('assert_cmpge.tz', 'Unit', '(Pair 0 -1)', 'Unit'), + ('assert_cmpge.tz', 'Unit', '(Pair 0 0)', 'Unit'), + # Tests the SET_CAR and SET_CDR instructions + ( + 'set_caddaadr.tz', + '(Pair (Pair 1 2 (Pair (Pair 3 0) 4) 5) 6)', + '3000000', + '(Pair (Pair 1 2 (Pair (Pair 3 3000000) 4) 5) 6)', + ), + ( + 'map_caddaadr.tz', + '(Pair (Pair 1 2 (Pair (Pair 3 0) 4) 5) 6)', + 'Unit', + '(Pair (Pair 1 2 (Pair (Pair 3 1000000) 4) 5) 6)', + ), + # Test comparisons on bytes { EQ ; GT ; LT ; GE ; LE } + ( + 'compare_bytes.tz', + '{}', + '(Pair 0x33 0x34)', + '{ False ; False ; True ; False ; True }', + ), + ( + 'compare_bytes.tz', + '{}', + '(Pair 0x33 0x33aa)', + '{ False ; False ; True ; False ; True }', + ), + ( + 'compare_bytes.tz', + '{}', + '(Pair 0x33 0x33)', + '{ True ; False ; False ; True ; True }', + ), + ( + 'compare_bytes.tz', + '{}', + '(Pair 0x34 0x33)', + '{ False ; True ; False ; True ; False }', + ), + ], + ) + def test_contract_input_output( + self, + client: Client, + contract: str, + param: str, + storage: str, + expected: str, + ): + assert contract.endswith( + '.tz' + ), "test contract should have .tz extension" + contract = path.join(MACROS_CONTRACT_PATH, contract) + run_script_res = client.run_script(contract, param, storage) + assert run_script_res.storage == expected + + @pytest.mark.parametrize( + "contract,param,storage", + [ # FORMAT: assert_output contract_file storage input expected_result + ('assert.tz', 'Unit', 'False'), + ('assert_eq.tz', 'Unit', '(Pair 0 -1)'), + ('assert_eq.tz', 'Unit', '(Pair 0 -1)'), + ('assert_neq.tz', 'Unit', '(Pair -1 -1)'), + ('assert_lt.tz', 'Unit', '(Pair 0 -1)'), + ('assert_lt.tz', 'Unit', '(Pair 0 0)'), + ('assert_le.tz', 'Unit', '(Pair 0 -1)'), + ('assert_gt.tz', 'Unit', '(Pair -1 0)'), + ('assert_gt.tz', 'Unit', '(Pair 0 0)'), + ('assert_ge.tz', 'Unit', '(Pair -1 0)'), + ('assert_cmpeq.tz', 'Unit', '(Pair 0 -1)'), + ('assert_cmpneq.tz', 'Unit', '(Pair -1 -1)'), + ('assert_cmplt.tz', 'Unit', '(Pair 0 0)'), + ('assert_cmplt.tz', 'Unit', '(Pair 0 -1)'), + ('assert_cmple.tz', 'Unit', '(Pair 0 -1)'), + ('assert_cmpgt.tz', 'Unit', '(Pair 0 0)'), + ('assert_cmpgt.tz', 'Unit', '(Pair -1 0)'), + ('assert_cmpge.tz', 'Unit', '(Pair -1 0)'), + ], + ) + def test_contract_failures(self, client: Client, contract, param, storage): + contract = path.join(MACROS_CONTRACT_PATH, contract) + assert_run_script_failwith(client, contract, param, storage) + + +@pytest.mark.slow +@pytest.mark.contract +class TestGuestBook: + """Test on the guestbook contract.""" + + def test_guestbook(self, client: Client): + contract = path.join(MACROS_CONTRACT_PATH, 'guestbook.tz') + + init_with_transfer( + client, + contract, + '{ Elt "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" None }', + 100, + 'bootstrap1', + ) + + assert_transfer_failwith( + client, + 0, + 'bootstrap2', + 'guestbook', + ['--arg', '"Pas moi"', '--burn-cap', '10'], + ) + + client.transfer( + 0, + 'bootstrap1', + 'guestbook', + ['-arg', '"Coucou"', '--burn-cap', '10'], + ) + bake(client) + assert_storage_contains( + client, + 'guestbook', + '{ Elt "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" (Some "Coucou") }', + ) + + assert_transfer_failwith( + client, + 0, + 'bootstrap3', + 'guestbook', + ['--arg', '"Pas moi non plus"', '--burn-cap', '10'], + ) + assert_transfer_failwith( + client, + 0, + 'bootstrap1', + 'guestbook', + ['--arg', '"Recoucou ?"', '--burn-cap', '10'], + ) + + +@pytest.mark.slow +@pytest.mark.contract +class TestBigmap: + """Tests on the big_map_mem contract.""" + + def test_bigmap(self, client: Client): + contract = path.join(MACROS_CONTRACT_PATH, 'big_map_mem.tz') + + init_with_transfer( + client, + contract, + '(Pair { Elt 1 Unit ; Elt 2 Unit ; Elt 3 Unit } Unit)', + 100, + 'bootstrap1', + ) + + client.transfer( + 1, + 'bootstrap1', + 'big_map_mem', + ['-arg', '(Pair 0 False)', '--burn-cap', '10'], + ) + bake(client) + + assert_transfer_failwith( + client, + 0, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 0 True)', '--burn-cap', '10'], + ) + + client.transfer( + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 0 False)', '--burn-cap', '10'], + ) + bake(client) + assert_transfer_failwith( + client, + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 0 True)', '--burn-cap', '10'], + ) + client.transfer( + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 1 True)', '--burn-cap', '10'], + ) + bake(client) + assert_transfer_failwith( + client, + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 1 False)', '--burn-cap', '10'], + ) + client.transfer( + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 2 True)', '--burn-cap', '10'], + ) + bake(client) + assert_transfer_failwith( + client, + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 2 False)', '--burn-cap', '10'], + ) + client.transfer( + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 3 True)', '--burn-cap', '10'], + ) + bake(client) + assert_transfer_failwith( + client, + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 3 False)', '--burn-cap', '10'], + ) + client.transfer( + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 4 False)', '--burn-cap', '10'], + ) + bake(client) + assert_transfer_failwith( + client, + 1, + 'bootstrap1', + 'big_map_mem', + ['--arg', '(Pair 4 True)', '--burn-cap', '10'], + ) + + +@pytest.mark.slow +@pytest.mark.contract +class TestBigmapGetAdd: + """Tests on the big_map_get_add contract.""" + + def test_bigmap(self, client: Client): + contract = path.join(MACROS_CONTRACT_PATH, 'big_map_get_add.tz') + + init_with_transfer( + client, + contract, + '(Pair { Elt 0 1 ; Elt 1 2 ; Elt 2 3 } Unit)', + 100, + 'bootstrap1', + ) + + client.transfer( + 1, + 'bootstrap1', + 'big_map_get_add', + [ + '--arg', + '(Pair (Pair 200 (Some 2)) (Pair 200 (Some 2)))', + '--burn-cap', + '10', + ], + ) + bake(client) + client.transfer( + 1, + 'bootstrap1', + 'big_map_get_add', + [ + '--arg', + '(Pair (Pair 200 None) (Pair 200 None))', + '--burn-cap', + '10', + ], + ) + bake(client) + client.transfer( + 1, + 'bootstrap1', + 'big_map_get_add', + [ + '--arg', + '(Pair (Pair 200 None) (Pair 300 None))', + '--burn-cap', + '10', + ], + ) + bake(client) + client.transfer( + 1, + 'bootstrap1', + 'big_map_get_add', + [ + '--arg', + '(Pair (Pair 1 None) (Pair 200 None))', + '--burn-cap', + '10', + ], + ) + bake(client) + client.transfer( + 1, + 'bootstrap1', + 'big_map_get_add', + [ + '--arg', + '(Pair (Pair 1 (Some 2)) (Pair 0 (Some 1)))', + '--burn-cap', + '10', + ], + ) + bake(client) + client.transfer( + 1, + 'bootstrap1', + 'big_map_get_add', + [ + '--arg', + '(Pair (Pair 400 (Some 1232)) (Pair 400 (Some 1232)))', + '--burn-cap', + '10', + ], + ) + bake(client) + client.transfer( + 1, + 'bootstrap1', + 'big_map_get_add', + [ + '--arg', + '(Pair (Pair 401 (Some 0)) (Pair 400 (Some 1232)))', + '--burn-cap', + '10', + ], + ) + bake(client) + + +@pytest.mark.regression +class TestMacroExpansion: + """Test expanding macros""" + + @pytest.mark.parametrize("contract", all_contracts(['macros'])) + def test_macro_expansion( + self, client_regtest: ClientRegression, contract: str + ): + """This test expands macros in all macro test contracts, with + regression detection enabled. This test should fail if the definition + of any macros change. + """ + client_regtest.expand_macros(path.join(CONTRACT_PATH, contract)) diff --git a/tests_python/tests_009/test_contract_onchain_opcodes.py b/tests_python/tests_009/test_contract_onchain_opcodes.py new file mode 100644 index 0000000000000000000000000000000000000000..cee037c833af880bbe4f79ba743886b6fb8ede51 --- /dev/null +++ b/tests_python/tests_009/test_contract_onchain_opcodes.py @@ -0,0 +1,1308 @@ +from os import path + +import pytest +from tools.client_regression import ClientRegression +from tools import paths +from tools.utils import ( + assert_run_failure, + assert_storage_contains, + bake, + init_with_transfer, + assert_balance, +) +from tools.constants import IDENTITIES +from .contract_paths import OPCODES_CONTRACT_PATH, MINI_SCENARIOS_CONTRACT_PATH + +KEY1 = 'foo' +KEY2 = 'bar' + + +@pytest.mark.incremental +@pytest.mark.slow +@pytest.mark.contract +@pytest.mark.regression +class TestContractOnchainOpcodes: + """Tests for individual opcodes that requires origination.""" + + def test_gen_keys(self, client_regtest_scrubbed: ClientRegression): + """Add keys used by later tests.""" + client = client_regtest_scrubbed + client.gen_key(KEY1) + client.gen_key(KEY2) + + def test_store_input(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + client.transfer(1000, "bootstrap1", KEY1, ['--burn-cap', '0.257']) + bake(client) + + client.transfer(2000, "bootstrap1", KEY2, ['--burn-cap', '0.257']) + bake(client) + + assert_balance(client, KEY1, 1000) + assert_balance(client, KEY2, 2000) + + # Create a contract and transfer 100 ꜩ to it + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'store_input.tz'), + '""', + 100, + 'bootstrap1', + ) + + client.transfer( + 100, + "bootstrap1", + "store_input", + ["-arg", '"abcdefg"', '--burn-cap', '10'], + ) + bake(client) + + assert_balance(client, "store_input", 200) + + assert_storage_contains(client, "store_input", '"abcdefg"') + + client.transfer( + 100, + "bootstrap1", + "store_input", + ["-arg", '"xyz"', '--burn-cap', '10'], + ) + bake(client) + + assert_storage_contains(client, "store_input", '"xyz"') + + def test_transfer_amount(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'transfer_amount.tz'), + '0', + 100, + 'bootstrap1', + ) + + client.transfer( + 500, + "bootstrap1", + 'transfer_amount', + ['-arg', 'Unit', '--burn-cap', '10'], + ) + + bake(client) + + assert_storage_contains(client, "transfer_amount", '500000000') + + def test_now(self, client_regtest_scrubbed: ClientRegression): + # Regtest is disabled for this test, since one would need to + # scrub storage for this one as it changes (the timestamp) + # on every run. + client = client_regtest_scrubbed + client.set_regtest(None) + + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'store_now.tz'), + '"2017-07-13T09:19:01Z"', + 100, + 'bootstrap1', + ) + + client.transfer( + 500, "bootstrap1", 'store_now', ['-arg', 'Unit', '--burn-cap', '10'] + ) + bake(client) + + assert_storage_contains(client, 'store_now', f'"{client.get_now()}"') + + def test_transfer_tokens(self, client_regtest_scrubbed: ClientRegression): + """Tests TRANSFER_TOKENS.""" + client = client_regtest_scrubbed + client.originate( + 'test_transfer_account1', + 100, + 'bootstrap1', + path.join(OPCODES_CONTRACT_PATH, 'noop.tz'), + ['--burn-cap', '10'], + ) + bake(client) + + client.originate( + 'test_transfer_account2', + 20, + 'bootstrap1', + path.join(OPCODES_CONTRACT_PATH, 'noop.tz'), + ['--burn-cap', '10'], + ) + bake(client) + + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'transfer_tokens.tz'), + 'Unit', + 1000, + 'bootstrap1', + ) + + assert_balance(client, 'test_transfer_account1', 100) + + account1_addr = client.get_contract_address('test_transfer_account1') + client.transfer( + 100, + 'bootstrap1', + 'transfer_tokens', + ['-arg', f'"{account1_addr}"', '--burn-cap', '10'], + ) + bake(client) + + # Why isn't this 200 ꜩ? Baking fee? + assert_balance(client, 'test_transfer_account1', 200) + + account2_addr = client.get_contract_address('test_transfer_account2') + client.transfer( + 100, + 'bootstrap1', + 'transfer_tokens', + ['-arg', f'"{account2_addr}"', '--burn-cap', '10'], + ) + bake(client) + + assert_balance(client, 'test_transfer_account2', 120) + + def test_self(self, client_regtest_scrubbed: ClientRegression): + # Regtest is disabled for this test, since one would need to + # scrub storage for this one as it changes (the contract + # address) on every run. + client = client_regtest_scrubbed + client.set_regtest(None) + + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'self.tz'), + '"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"', + 1000, + 'bootstrap1', + ) + + client.transfer(0, 'bootstrap1', 'self', ['--burn-cap', '10']) + bake(client) + + self_addr = client.get_contract_address('self') + assert_storage_contains(client, 'self', f'"{self_addr}"') + + def test_contract_fails(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + client.set_regtest(None) + + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'contract.tz'), + 'Unit', + 1000, + 'bootstrap1', + ) + + client.transfer(0, 'bootstrap1', 'self', ['--burn-cap', '10']) + bake(client) + addr = client.get_contract_address('contract') + + with assert_run_failure(r'script reached FAILWITH instruction'): + client.transfer( + 0, + 'bootstrap1', + 'contract', + ['-arg', f'"{addr}"', '--burn-cap', '10'], + ) + + def test_init_proxy(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'proxy.tz'), + 'Unit', + 1000, + 'bootstrap1', + ) + + def test_source(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + init_store = IDENTITIES['bootstrap4']['identity'] + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'source.tz'), + f'"{init_store}"', + 1000, + 'bootstrap1', + ) + + # direct transfer to the contract + client.transfer(0, 'bootstrap2', 'source', ['--burn-cap', '10']) + bake(client) + + source_addr = IDENTITIES['bootstrap2']['identity'] + assert_storage_contains(client, 'source', f'"{source_addr}"') + + # indirect transfer to the contract through proxy + contract_addr = client.get_contract_address('source') + client.transfer( + 0, + 'bootstrap2', + 'proxy', + ['--burn-cap', '10', '--arg', f'"{contract_addr}"'], + ) + bake(client) + assert_storage_contains(client, 'source', f'"{source_addr}"') + + def test_sender(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + client.set_regtest(None) + + init_store = IDENTITIES['bootstrap4']['identity'] + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'sender.tz'), + f'"{init_store}"', + 1000, + 'bootstrap1', + ) + + # direct transfer to the contract + client.transfer(0, 'bootstrap2', 'sender', ['--burn-cap', '10']) + bake(client) + + sender_addr = IDENTITIES['bootstrap2']['identity'] + assert_storage_contains(client, 'sender', f'"{sender_addr}"') + + # indirect transfer to the contract through proxy + contract_addr = client.get_contract_address('sender') + proxy_addr = client.get_contract_address('proxy') + client.transfer( + 0, + 'bootstrap2', + 'proxy', + ['--burn-cap', '10', '--arg', f'"{contract_addr}"'], + ) + bake(client) + assert_storage_contains(client, 'sender', f'"{proxy_addr}"') + + def test_slice(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'slices.tz'), + '"sppk7dBPqMPjDjXgKbb5f7V3PuKUrA4Zuwc3c3H7XqQerqPUWbK7Hna"', + 1000, + 'bootstrap1', + ) + + @pytest.mark.parametrize( + 'contract_arg', + [ + line.rstrip('\n') + for line in open( + f'{paths.TEZOS_HOME}' + + '/tests_python/tests_alpha/' + + 'test_slice_fails_params.txt' + ) + ], + ) + def test_slice_fails( + self, client_regtest_scrubbed: ClientRegression, contract_arg: str + ): + client = client_regtest_scrubbed + + with assert_run_failure(r'script reached FAILWITH instruction'): + client.transfer( + 0, + 'bootstrap1', + 'slices', + ['-arg', contract_arg, '--burn-cap', '10'], + ) + # bake(client) + + @pytest.mark.parametrize( + 'contract_arg', + [ + line.rstrip('\n') + for line in open( + f'{paths.TEZOS_HOME}' + + '/tests_python/tests_alpha/' + + 'test_slice_success_params.txt' + ) + ], + ) + def test_slice_success( + self, client_regtest_scrubbed: ClientRegression, contract_arg: str + ): + client = client_regtest_scrubbed + client.transfer( + 0, + 'bootstrap1', + 'slices', + ['-arg', contract_arg, '--burn-cap', '10'], + ) + bake(client) + + def test_split_string(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'split_string.tz'), + '{}', + 1000, + 'bootstrap1', + ) + + client.transfer( + 0, + 'bootstrap1', + 'split_string', + ['-arg', '"abc"', '--burn-cap', '10'], + ) + bake(client) + assert_storage_contains(client, 'split_string', '{ "a" ; "b" ; "c" }') + + client.transfer( + 0, + 'bootstrap1', + 'split_string', + ['-arg', '"def"', '--burn-cap', '10'], + ) + bake(client) + assert_storage_contains( + client, 'split_string', '{ "a" ; "b" ; "c" ; "d" ; "e" ; "f" }' + ) + + def test_split_bytes(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'split_bytes.tz'), + '{}', + 1000, + 'bootstrap1', + ) + + client.transfer( + 0, + 'bootstrap1', + 'split_bytes', + ['-arg', '0xaabbcc', '--burn-cap', '10'], + ) + bake(client) + assert_storage_contains(client, 'split_bytes', '{ 0xaa ; 0xbb ; 0xcc }') + + client.transfer( + 0, + 'bootstrap1', + 'split_bytes', + ['-arg', '0xddeeff', '--burn-cap', '10'], + ) + bake(client) + assert_storage_contains( + client, 'split_bytes', '{ 0xaa ; 0xbb ; 0xcc ; 0xdd ; 0xee ; 0xff }' + ) + + def test_set_delegate(self, client_regtest_scrubbed: ClientRegression): + client = client_regtest_scrubbed + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'set_delegate.tz'), + 'Unit', + 1000, + 'bootstrap1', + ) + bake(client) + + assert client.get_delegate('set_delegate').delegate is None + + addr = IDENTITIES['bootstrap5']['identity'] + client.transfer( + 0, 'bootstrap1', 'set_delegate', ['-arg', f'(Some "{addr}")'] + ) + bake(client) + + assert client.get_delegate('set_delegate').delegate == addr + + client.transfer(0, 'bootstrap1', 'set_delegate', ['-arg', 'None']) + bake(client) + + assert client.get_delegate('set_delegate').delegate is None + + @pytest.mark.parametrize( + 'contract', + [ + 'compare_big_type.tz', + 'compare_big_type2.tz', + ], + ) + def test_trace_origination(self, client_regtest_scrubbed, contract): + client = client_regtest_scrubbed + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, contract), + 'Unit', + 1000, + 'bootstrap1', + ) + bake(client) + + +class TestTickets: + """Tests for tickets.""" + + def test_ticket_user_forge(self, client): + bake(client) + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticket_store-2.tz'), + 'None', + 100, + 'bootstrap1', + 'storer', + ) + + # Create parameter by hand with a ticket type but no ticket in it + client.transfer( + 100, 'bootstrap1', 'storer', ['-arg', 'None', '--burn-cap', '10'] + ) + + with assert_run_failure(r'Unexpected forged value'): + # Create parameter by hand with a ticket in it + client.transfer( + 100, + 'bootstrap1', + 'storer', + ['-arg', 'Some 1', '--burn-cap', '10'], + ) + + with assert_run_failure(r'Unexpected forged value'): + # Create storage by hand with a ticket in it + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticket_bad.tz'), + '1', + 100, + 'bootstrap1', + 'ticket_bad', + ) + + def test_ticket_user_big_forge(self, client): + bake(client) + contract_name = 'big_storer' + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticket_big_store.tz'), + '{}', + 100, + 'bootstrap1', + contract_name, + ) + bake(client) + client.transfer( + 100, 'bootstrap1', contract_name, ['-arg', '42', '--burn-cap', '10'] + ) + bake(client) + storage = client.get_storage(contract_name) + + with assert_run_failure(r'Unexpected forged value'): + # Create a storage with the ID of a big map that has tickets in it + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticket_big_store.tz'), + storage, + 100, + 'bootstrap1', + 'thief', + ) + + with assert_run_failure(r'Unexpected forged value'): + # Create a storage with the ID of a big map that has tickets in it + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticket_big_store.tz'), + '(Pair ' + storage + ' {})', + 100, + 'bootstrap1', + 'thief', + ) + + def test_ticket_read(self, client): + """Test TICKETS""" + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticketer.tz'), + '42', + 100, + 'bootstrap1', + 'ticketer_read', + ) + bake(client) + ticketer_addr = client.get_contract_address('ticketer_read') + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticket_read.tz'), + '"' + ticketer_addr + '"', + 100, + 'bootstrap1', + 'reader', + ) + bake(client) + reader_addr = client.get_contract_address('reader') + client.transfer( + 100, + 'bootstrap1', + 'ticketer_read', + ['-arg', '"' + reader_addr + '"', '--burn-cap', '10'], + ) + bake(client) + assert_storage_contains(client, "reader", '"' + ticketer_addr + '"') + + def test_bad_ticket(self, client): + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticketer.tz'), + '42', + 100, + 'bootstrap1', + 'ticketer_bad', + ) + bake(client) + ticketer_addr = client.get_contract_address('ticketer_bad') + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticket_read.tz'), + '"' + ticketer_addr + '"', + 100, + 'bootstrap1', + 'reader_bad', + ) + bake(client) + with assert_run_failure(r'Unexpected forged value'): + client.transfer( + 100, + 'bootstrap1', + 'reader_bad', + ['-arg', '1', '--burn-cap', '10'], + ) + bake(client) + + def test_ticket_utxo(self, client): + """Test UTXOs""" + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'utxor.tz'), + '42', + 100, + 'bootstrap1', + ) + bake(client) + utxor_addr = client.get_contract_address('utxor') + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'utxo_read.tz'), + '"' + utxor_addr + '"', + 100, + 'bootstrap1', + "reader_a", + ) + bake(client) + reader_a_addr = client.get_contract_address('reader_a') + utxor_addr = client.get_contract_address('utxor') + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'utxo_read.tz'), + '"' + utxor_addr + '"', + 100, + 'bootstrap1', + "reader_b", + ) + bake(client) + reader_b_addr = client.get_contract_address('reader_b') + client.transfer( + 100, + 'bootstrap1', + 'utxor', + [ + '-arg', + '(Pair "' + reader_a_addr + '" "' + reader_b_addr + '")', + '--burn-cap', + '10', + ], + ) + bake(client) + + def test_ticket_split(self, client): + def ticket(target_addr, param, utxo_amount): + param = ( + '(Pair (Pair "' + + target_addr + + '" ' + + str(param) + + ') ' + + str(utxo_amount) + + ')' + ) + client.transfer( + 100, + 'bootstrap1', + 'ticketer', + ['-arg', param, '--burn-cap', '10'], + ) + + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticketer-2.tz'), + 'Unit', + 100, + 'bootstrap1', + 'ticketer', + ) + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticket_split.tz'), + 'Unit', + 100, + 'bootstrap1', + 'splitter', + ) + bake(client) + splitter_addr = client.get_contract_address('splitter') + ticket(splitter_addr, 42, 3) + with assert_run_failure(r'script reached FAILWITH instruction'): + # Wrong Split Amount + ticket(splitter_addr, 42, 4) + bake(client) + + def test_ticket_join(self, client): + """Test JOIN""" + + def params(target_addr, utxo_amount, param): + return ( + '(Pair (Pair "' + + target_addr + + '" ' + + str(param) + + ') ' + + str(utxo_amount) + + ')' + ) + + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticketer-2.tz'), + 'Unit', + 100, + 'bootstrap1', + 'ticketer_a', + ) + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticketer-2.tz'), + 'Unit', + 100, + 'bootstrap1', + 'ticketer_b', + ) + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'ticket_join.tz'), + 'None', + 100, + 'bootstrap1', + 'joiner', + ) + bake(client) + joiner_addr = client.get_contract_address('joiner') + client.transfer( + 100, + 'bootstrap1', + 'ticketer_a', + ['-arg', params(joiner_addr, 42, 1), '--burn-cap', '10'], + ) + bake(client) + client.transfer( + 100, + 'bootstrap1', + 'ticketer_a', + ['-arg', params(joiner_addr, 144, 1), '--burn-cap', '10'], + ) + bake(client) + with assert_run_failure(r'script reached FAILWITH instruction'): + # Different Ticketer + client.transfer( + 100, + 'bootstrap1', + 'ticketer_b', + ['-arg', params(joiner_addr, 23, 1), '--burn-cap', '10'], + ) + with assert_run_failure(r'script reached FAILWITH instruction'): + # Different Content + client.transfer( + 100, + 'bootstrap1', + 'ticketer_a', + ['-arg', params(joiner_addr, 21, 23), '--burn-cap', '10'], + ) + + def test_ticket_fungible_originations(self, client, session): + """Test the origination of builder and wallet contracts for fungible + tokens implemented using tickets.""" + + builder_path = path.join( + MINI_SCENARIOS_CONTRACT_PATH, 'ticket_builder_fungible.tz' + ) + + wallet_path = path.join( + MINI_SCENARIOS_CONTRACT_PATH, 'ticket_wallet_fungible.tz' + ) + + manager_address = IDENTITIES['bootstrap1']['identity'] + + builders = {} + wallets = {} + + # Helper functions + def originate_builder(name): + """Create a fungible token contract managed by bootstrap1.""" + origination = client.originate( + contract_name=f'builder_{name}', + amount="0", + sender='bootstrap1', + contract=builder_path, + args=['--init', f'"{manager_address}"', '--burn-cap', "10"], + ) + builders[name] = origination.contract + bake(client) + + def originate_wallet(name): + """Create a fungible token wallet managed by bootstrap1.""" + origination = client.originate( + contract_name=f'wallet_{name}', + amount="0", + sender='bootstrap1', + contract=wallet_path, + args=[ + '--init', + f'Pair "{manager_address}" {{}}', + '--burn-cap', + "10", + ], + ) + wallets[name] = origination.contract + bake(client) + + # Create 3 token contracts "A", "B", and "C". + originate_builder("A") + originate_builder("B") + originate_builder("C") + + # Create 2 wallets "Alice" and "Bob". + originate_wallet("Alice") + originate_wallet("Bob") + + session['fungible_builders'] = builders + session['fungible_wallets'] = wallets + + def test_ticket_fungible_transfers(self, client, session): + """Test the life cycle of fungible tokens implemented using tickets.""" + + manager_address = IDENTITIES['bootstrap1']['identity'] + + builders = session['fungible_builders'] + wallets = session['fungible_wallets'] + + def mint(builder, wallet, amount): + """Mint fungible tokens.""" + wallet_address = wallets[wallet] + parameter = f'(Pair "{wallet_address}%receive" {amount})' + client.transfer( + amount=0, + giver=manager_address, + receiver=f'builder_{builder}', + args=[ + '--burn-cap', + '2', + '--entrypoint', + 'mint', + '--arg', + parameter, + ], + ) + bake(client) + + def burn(builder, wallet, amount): + """Burn fungible tokens.""" + builder_addr = builders[builder] + parameter = f'Pair "{builder_addr}%burn" {amount} "{builder_addr}"' + client.transfer( + amount=0, + giver=manager_address, + receiver=f'wallet_{wallet}', + args=[ + '--burn-cap', + '2', + '--entrypoint', + 'send', + '--arg', + parameter, + ], + ) + bake(client) + + def transfer(builder, source_wallet, destination_wallet, amount): + """Transfer fungible tokens.""" + builder_addr = builders[builder] + dest_addr = wallets[destination_wallet] + parameter = f'Pair "{dest_addr}%receive" {amount} "{builder_addr}"' + client.transfer( + amount=0, + giver=manager_address, + receiver=f'wallet_{source_wallet}', + args=[ + '--burn-cap', + '2', + '--entrypoint', + 'send', + '--arg', + parameter, + ], + ) + bake(client) + + # 100A --> Alice + mint(builder="A", wallet="Alice", amount=100) + # 100B --> Alice + mint(builder="B", wallet="Alice", amount=100) + + # Fail: Alice --1C--> Bob + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="C", + source_wallet="Alice", + destination_wallet="Bob", + amount=1, + ) + + # Fail: Alice --0C--> Bob + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="C", + source_wallet="Alice", + destination_wallet="Bob", + amount=0, + ) + + # Fail: Alice --150A--> Bob + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="A", + source_wallet="Alice", + destination_wallet="Bob", + amount=150, + ) + + # Fail: Bob --50A--> Alice + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="A", + source_wallet="Bob", + destination_wallet="Alice", + amount=50, + ) + + # Alice --50A--> Bob + transfer( + builder="A", + source_wallet="Alice", + destination_wallet="Bob", + amount=50, + ) + + # Alice --50A--> Bob + transfer( + builder="A", + source_wallet="Alice", + destination_wallet="Bob", + amount=50, + ) + + # Alice --0A--> Bob + transfer( + builder="A", + source_wallet="Alice", + destination_wallet="Bob", + amount=0, + ) + + # Fail: Alice --1A--> Bob + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="A", + source_wallet="Alice", + destination_wallet="Bob", + amount=1, + ) + + # Bob --100A--> Bob + transfer( + builder="A", + source_wallet="Bob", + destination_wallet="Bob", + amount=100, + ) + + # Fail: Bob --150A--> Bob + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="A", + source_wallet="Bob", + destination_wallet="Bob", + amount=150, + ) + + # Bob --100A--> + burn(builder="A", wallet="Bob", amount=100) + + # Bob --0A--> + burn(builder="A", wallet="Bob", amount=0) + + # Fail: Bob --1A--> + with assert_run_failure(r'script reached FAILWITH instruction'): + burn(builder="A", wallet="Bob", amount=1) + + def test_ticket_non_fungible_originations(self, client, session): + """Test the origination of builder and wallet contracts for + non-fungible tokens implemented using tickets.""" + + builder_path = path.join( + MINI_SCENARIOS_CONTRACT_PATH, 'ticket_builder_non_fungible.tz' + ) + + wallet_path = path.join( + MINI_SCENARIOS_CONTRACT_PATH, 'ticket_wallet_non_fungible.tz' + ) + + manager_address = IDENTITIES['bootstrap1']['identity'] + + builders = {} + wallets = {} + + # Helper functions + def originate_builder(name): + """Create a non-fungible token contract managed by bootstrap1.""" + storage = f'(Pair "{manager_address}" 0)' + origination = client.originate( + contract_name=f'nft_builder_{name}', + amount="0", + sender='bootstrap1', + contract=builder_path, + args=['--init', storage, '--burn-cap', "10"], + ) + builders[name] = origination.contract + bake(client) + + def originate_wallet(name): + """Create a non-fungible token wallet managed by bootstrap1.""" + origination = client.originate( + contract_name=f'nft_wallet_{name}', + amount="0", + sender='bootstrap1', + contract=wallet_path, + args=[ + '--init', + f'Pair "{manager_address}" {{}}', + '--burn-cap', + "10", + ], + ) + wallets[name] = origination.contract + bake(client) + + # Create 3 token contracts "A", "B", and "C". + originate_builder("A") + originate_builder("B") + originate_builder("C") + + # Create 2 wallets "Alice" and "Bob". + originate_wallet("Alice") + originate_wallet("Bob") + + session['non_fungible_builders'] = builders + session['non_fungible_wallets'] = wallets + + def test_ticket_non_fungible_transfers(self, client, session): + """Test the life cycle of non-fungible tokens implemented using + tickets.""" + + manager_address = IDENTITIES['bootstrap1']['identity'] + + builders = session['non_fungible_builders'] + wallets = session['non_fungible_wallets'] + + def mint(builder, wallet, token_id): + """Mint a non-fungible token and assert that it has the expected + id.""" + builder_alias = f'nft_builder_{builder}' + expected_builder_storage = f'Pair "{manager_address}" {token_id}' + actual_builder_storage = client.get_storage(builder_alias) + assert expected_builder_storage == actual_builder_storage + + wallet_address = wallets[wallet] + parameter = f'"{wallet_address}%receive"' + client.transfer( + amount=0, + giver=manager_address, + receiver=builder_alias, + args=[ + '--burn-cap', + '2', + '--entrypoint', + 'mint_destination', + '--arg', + parameter, + ], + ) + bake(client) + + def burn(builder, wallet, token_id): + """Burn a non-fungible token.""" + builder_addr = builders[builder] + parameter = ( + f'Pair "{builder_addr}%burn" "{builder_addr}" {token_id}' + ) + client.transfer( + amount=0, + giver=manager_address, + receiver=f'nft_wallet_{wallet}', + args=[ + '--burn-cap', + '2', + '--entrypoint', + 'send', + '--arg', + parameter, + ], + ) + bake(client) + + def transfer(builder, source_wallet, destination_wallet, token_id): + """Transfer fungible tokens.""" + builder_addr = builders[builder] + dest_addr = wallets[destination_wallet] + parameter = ( + f'Pair "{dest_addr}%receive" "{builder_addr}" {token_id}' + ) + client.transfer( + amount=0, + giver=manager_address, + receiver=f'nft_wallet_{source_wallet}', + args=[ + '--burn-cap', + '2', + '--entrypoint', + 'send', + '--arg', + parameter, + ], + ) + bake(client) + + # A0 --> Alice + mint(builder="A", wallet="Alice", token_id=0) + # A1 --> Alice + mint(builder="A", wallet="Alice", token_id=1) + # B0 --> Alice + mint(builder="B", wallet="Alice", token_id=0) + + # Fail: Alice --C0--> Bob + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="C", + source_wallet="Alice", + destination_wallet="Bob", + token_id=0, + ) + + # Fail: Alice --A2--> Bob + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="A", + source_wallet="Alice", + destination_wallet="Bob", + token_id=2, + ) + + # Fail: Bob --A0--> Alice + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="A", + source_wallet="Bob", + destination_wallet="Alice", + token_id=0, + ) + + # Fail: Bob --A1--> Bob + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="A", + source_wallet="Bob", + destination_wallet="Bob", + token_id=1, + ) + + # Alice --A1--> Bob + transfer( + builder="A", + source_wallet="Alice", + destination_wallet="Bob", + token_id=1, + ) + + # Alice --A0--> Bob + transfer( + builder="A", + source_wallet="Alice", + destination_wallet="Bob", + token_id=0, + ) + + # Fail: Alice --A1--> Bob + with assert_run_failure(r'script reached FAILWITH instruction'): + transfer( + builder="A", + source_wallet="Alice", + destination_wallet="Bob", + token_id=1, + ) + + # Bob --A0--> Bob + transfer( + builder="A", + source_wallet="Bob", + destination_wallet="Bob", + token_id=0, + ) + + # Bob --A0--> + burn(builder="A", wallet="Bob", token_id=0) + + # Bob --A1--> + burn(builder="A", wallet="Bob", token_id=1) + + # Fail: Bob --B0--> + with assert_run_failure(r'script reached FAILWITH instruction'): + burn(builder="B", wallet="Bob", token_id=0) + + # Alice --B0--> + burn(builder="B", wallet="Alice", token_id=0) + + +ORIGINATE_BIG_MAP_FILE = path.join( + OPCODES_CONTRACT_PATH, 'originate_big_map.tz' +) + + +@pytest.mark.incremental +@pytest.mark.contract +@pytest.mark.regression +class TestContractBigMapOrigination: + def test_big_map_origination_literal(self, client_regtest_scrubbed): + client = client_regtest_scrubbed + # originate a first version of the contract from a literal so + # that a big_map with id 0 exists + init_with_transfer( + client, + ORIGINATE_BIG_MAP_FILE, + '{Elt 0 0}', + 1000, + 'bootstrap1', + contract_name='originate_big_map_literal', + ) + + def test_big_map_origination_id(self, client_regtest_scrubbed): + client = client_regtest_scrubbed + # originate again the same script from the big-map id 0 + with assert_run_failure(r'Unexpected forged value'): + init_with_transfer( + client, + ORIGINATE_BIG_MAP_FILE, + '0', + 1000, + 'bootstrap1', + contract_name='originate_big_map_id', + ) + + def test_big_map_origination_diff(self, client_regtest_scrubbed): + client = client_regtest_scrubbed + + # originate again the same script from a big-diff + with assert_run_failure(r'Unexpected forged value'): + init_with_transfer( + client, + ORIGINATE_BIG_MAP_FILE, + 'Pair 0 {Elt 1 (Some 4)}', + 1000, + 'bootstrap1', + contract_name='originate_big_map_diff', + ) + + def test_big_map_transfer_id(self, client_regtest_scrubbed): + client = client_regtest_scrubbed + # call the first contract, passing an id as parameter + with assert_run_failure(r'Unexpected forged value'): + client.call( + source='bootstrap1', + destination='originate_big_map_literal', + args=['--arg', '0'], + ) + + def test_big_map_transfer_diff(self, client_regtest_scrubbed): + client = client_regtest_scrubbed + # call the first contract, passing a diff as parameter + with assert_run_failure(r'Unexpected forged value'): + client.call( + source='bootstrap1', + destination='originate_big_map_literal', + args=['--arg', 'Pair 0 {Elt 1 (Some 4)}'], + ) + + +@pytest.mark.incremental +@pytest.mark.slow +@pytest.mark.contract +@pytest.mark.regression +class TestContractOnchainLevel: + """Onchain tests for LEVEL.""" + + # This test needs to be in a separate class to not depend on the number + # of operations happening before + + def test_level(self, client_regtest_scrubbed): + client = client_regtest_scrubbed + + init_with_transfer( + client, + path.join(OPCODES_CONTRACT_PATH, 'level.tz'), + '9999999', + 100, + 'bootstrap1', + ) + bake(client) + client.transfer( + 500, "bootstrap1", 'level', ['-arg', 'Unit', '--burn-cap', '10'] + ) + bake(client) + level = client.get_level() + slevel = str(level) + assert_storage_contains(client, 'level', slevel) + bake(client) + bake(client) + # checks the storage hasn't changed even though the current level has + assert_storage_contains(client, 'level', slevel) + # Run again to check the storage gets updated + client.transfer( + 500, "bootstrap1", 'level', ['-arg', 'Unit', '--burn-cap', '10'] + ) + bake(client) + assert_storage_contains(client, 'level', str(level + 3)) diff --git a/tests_python/tests_009/test_contract_opcodes.py b/tests_python/tests_009/test_contract_opcodes.py new file mode 100644 index 0000000000000000000000000000000000000000..edd625c21b3fc6edc009ad757097d68d8608c9f2 --- /dev/null +++ b/tests_python/tests_009/test_contract_opcodes.py @@ -0,0 +1,1905 @@ +from os import path + +import pytest + +from tools.client_regression import ClientRegression +from tools.constants import IDENTITIES +from tools.utils import ( + assert_run_failure, + assert_run_script_failwith, + assert_run_script_success, +) +from .contract_paths import MINI_SCENARIOS_CONTRACT_PATH, OPCODES_CONTRACT_PATH + + +PUBLIC_KEY = IDENTITIES['bootstrap1']['public'] + + +@pytest.mark.slow +@pytest.mark.contract +@pytest.mark.regression +class TestContractOpcodes: + """Tests for individual opcodes that do not require origination.""" + + @pytest.mark.parametrize( + "contract,param,storage,expected", + [ # FORMAT: assert_output contract_file storage input expected_result + # TODO add tests for map_car.tz, subset.tz + # NB: noop.tz is tested in test_basic.sh + ('cons.tz', '{}', '10', '{ 10 }'), + ('cons.tz', '{ 10 }', '-5', '{ -5 ; 10 }'), + ('cons.tz', '{ -5 ; 10 }', '99', '{ 99 ; -5 ; 10 }'), + # Tests on Options + ('none.tz', 'Some 10', 'Unit', 'None'), + ('ret_int.tz', 'None', 'Unit', '(Some 300)'), + # Map block on lists + ('list_map_block.tz', '{0}', '{}', '{}'), + ( + 'list_map_block.tz', + '{0}', + '{ 1 ; 1 ; 1 ; 1 }', + '{ 1 ; 2 ; 3 ; 4 }', + ), + ( + 'list_map_block.tz', + '{0}', + '{ 1 ; 2 ; 3 ; 0 }', + '{ 1 ; 3 ; 5 ; 3 }', + ), + # Reverse a list + ('reverse.tz', '{""}', '{}', '{}'), + ( + 'reverse.tz', + '{""}', + '{ "c" ; "b" ; "a" }', + '{ "a" ; "b" ; "c" }', + ), + # Reverse using LOOP_LEFT + ('loop_left.tz', '{""}', '{}', '{}'), + ( + 'loop_left.tz', + '{""}', + '{ "c" ; "b" ; "a" }', + '{ "a" ; "b" ; "c" }', + ), + # Identity on strings + ('str_id.tz', 'None', '"Hello"', '(Some "Hello")'), + ('str_id.tz', 'None', '"abcd"', '(Some "abcd")'), + # Slice strings + ('slice.tz', 'None', 'Pair 0 0', 'None'), + ('slice.tz', 'Some "Foo"', 'Pair 10 5', 'None'), + ('slice.tz', 'Some "Foo"', 'Pair 0 0', '(Some "")'), + ('slice.tz', 'Some "Foo"', 'Pair 0 10', 'None'), + ('slice.tz', 'Some "Foo"', 'Pair 0 2', '(Some "Fo")'), + ('slice.tz', 'Some "Foo"', 'Pair 1 3', 'None'), + ('slice.tz', 'Some "Foo"', 'Pair 1 1', '(Some "o")'), + # Stress-test the failure case of slice for a + # non-trivial gas consumption + ( + 'slice.tz', + 'Some' + '"' + 'Foo' * 2000 + '"', + 'Pair 1 10000', + 'None', + ), + # Slice bytes + ('slice_bytes.tz', 'None', 'Pair 0 1', 'None'), + ('slice_bytes.tz', 'Some 0xaabbcc', 'Pair 0 0', '(Some 0x)'), + ('slice_bytes.tz', 'Some 0xaabbcc', 'Pair 0 1', '(Some 0xaa)'), + ('slice_bytes.tz', 'Some 0xaabbcc', 'Pair 1 1', '(Some 0xbb)'), + ('slice_bytes.tz', 'Some 0xaabbcc', 'Pair 1 2', '(Some 0xbbcc)'), + ('slice_bytes.tz', 'Some 0xaabbcc', 'Pair 1 3', 'None'), + ('slice_bytes.tz', 'Some 0xaabbcc', 'Pair 1 1', '(Some 0xbb)'), + # Stress-test the failure case of slice for a + # non-trivial gas consumption + ( + 'slice_bytes.tz', + 'Some 0x' + 'aabbcc' * 2000, + 'Pair 1 10000', + 'None', + ), + # Identity on pairs + ( + 'pair_id.tz', + 'None', + '(Pair True False)', + '(Some (Pair True False))', + ), + ( + 'pair_id.tz', + 'None', + '(Pair False True)', + '(Some (Pair False True))', + ), + ( + 'pair_id.tz', + 'None', + '(Pair True True)', + '(Some (Pair True True))', + ), + ( + 'pair_id.tz', + 'None', + '(Pair False False)', + '(Some (Pair False False))', + ), + # Tests CAR and CDR instructions + ('car.tz', '0', '(Pair 34 17)', '34'), + ('cdr.tz', '0', '(Pair 34 17)', '17'), + # Logical not + ('not.tz', 'None', 'True', '(Some False)'), + ('not.tz', 'None', 'False', '(Some True)'), + # Logical and + ('and.tz', 'None', '(Pair False False)', '(Some False)'), + ('and.tz', 'None', '(Pair False True)', '(Some False)'), + ('and.tz', 'None', '(Pair True False)', '(Some False)'), + ('and.tz', 'None', '(Pair True True)', '(Some True)'), + # Logical or + ('or.tz', 'None', '(Pair False False)', '(Some False)'), + ('or.tz', 'None', '(Pair False True)', '(Some True)'), + ('or.tz', 'None', '(Pair True False)', '(Some True)'), + ('or.tz', 'None', '(Pair True True)', '(Some True)'), + # Logical and + ('and_logical_1.tz', 'False', "(Pair False False)", 'False'), + ('and_logical_1.tz', 'False', "(Pair False True)", 'False'), + ('and_logical_1.tz', 'False', "(Pair True False)", 'False'), + ('and_logical_1.tz', 'False', "(Pair True True)", 'True'), + # Binary and + ('and_binary.tz', 'Unit', 'Unit', 'Unit'), + # Binary or + ('or_binary.tz', 'None', '(Pair 4 8)', '(Some 12)'), + ('or_binary.tz', 'None', '(Pair 0 8)', '(Some 8)'), + ('or_binary.tz', 'None', '(Pair 8 0)', '(Some 8)'), + ('or_binary.tz', 'None', '(Pair 15 4)', '(Some 15)'), + ('or_binary.tz', 'None', '(Pair 14 1)', '(Some 15)'), + ('or_binary.tz', 'None', '(Pair 7 7)', '(Some 7)'), + # Binary not + ('not_binary.tz', 'None', '(Left 0)', '(Some -1)'), + ('not_binary.tz', 'None', '(Left 8)', '(Some -9)'), + ('not_binary.tz', 'None', '(Left 7)', '(Some -8)'), + ('not_binary.tz', 'None', '(Left -9)', '(Some 8)'), + ('not_binary.tz', 'None', '(Left -8)', '(Some 7)'), + ('not_binary.tz', 'None', '(Right 0)', '(Some -1)'), + ('not_binary.tz', 'None', '(Right 8)', '(Some -9)'), + ('not_binary.tz', 'None', '(Right 7)', '(Some -8)'), + # XOR + ( + 'xor.tz', + 'None', + 'Left (Pair False False)', + '(Some (Left False))', + ), + ('xor.tz', 'None', 'Left (Pair False True)', '(Some (Left True))'), + ('xor.tz', 'None', 'Left (Pair True False)', '(Some (Left True))'), + ('xor.tz', 'None', 'Left (Pair True True)', '(Some (Left False))'), + ('xor.tz', 'None', 'Right (Pair 0 0)', '(Some (Right 0))'), + ('xor.tz', 'None', 'Right (Pair 0 1)', '(Some (Right 1))'), + ('xor.tz', 'None', 'Right (Pair 1 0)', '(Some (Right 1))'), + ('xor.tz', 'None', 'Right (Pair 1 1)', '(Some (Right 0))'), + ('xor.tz', 'None', 'Right (Pair 42 21)', '(Some (Right 63))'), + ('xor.tz', 'None', 'Right (Pair 42 63)', '(Some (Right 21))'), + # test shifts: LSL & LSR + ('shifts.tz', 'None', '(Left (Pair 8 1))', '(Some 16)'), + ('shifts.tz', 'None', '(Left (Pair 0 0))', '(Some 0)'), + ('shifts.tz', 'None', '(Left (Pair 0 1))', '(Some 0)'), + ('shifts.tz', 'None', '(Left (Pair 1 2))', '(Some 4)'), + ('shifts.tz', 'None', '(Left (Pair 15 2))', '(Some 60)'), + ('shifts.tz', 'None', '(Right (Pair 8 1))', '(Some 4)'), + ('shifts.tz', 'None', '(Right (Pair 0 0))', '(Some 0)'), + ('shifts.tz', 'None', '(Right (Pair 0 1))', '(Some 0)'), + ('shifts.tz', 'None', '(Right (Pair 1 2))', '(Some 0)'), + ('shifts.tz', 'None', '(Right (Pair 15 2))', '(Some 3)'), + # Concatenate all strings of a list into one string + ('concat_list.tz', '""', '{ "a" ; "b" ; "c" }', '"abc"'), + ('concat_list.tz', '""', '{}', '""'), + ( + 'concat_list.tz', + '""', + '{ "Hello" ; " " ; "World" ; "!" }', + '"Hello World!"', + ), + # Concatenate the bytes in storage with all bytes in the given list + ('concat_hello_bytes.tz', '{}', '{ 0xcd }', '{ 0xffcd }'), + ('concat_hello_bytes.tz', '{}', '{}', '{}'), + ( + 'concat_hello_bytes.tz', + '{}', + '{ 0xab ; 0xcd }', + '{ 0xffab ; 0xffcd }', + ), + # Identity on lists + ( + 'list_id.tz', + '{""}', + '{ "1" ; "2" ; "3" }', + '{ "1" ; "2" ; "3" }', + ), + ('list_id.tz', '{""}', '{}', '{}'), + ( + 'list_id.tz', + '{""}', + '{ "a" ; "b" ; "c" }', + '{ "a" ; "b" ; "c" }', + ), + ( + 'list_id_map.tz', + '{""}', + '{ "1" ; "2" ; "3" }', + '{ "1" ; "2" ; "3" }', + ), + ('list_id_map.tz', '{""}', '{}', '{}'), + ( + 'list_id_map.tz', + '{""}', + '{ "a" ; "b" ; "c" }', + '{ "a" ; "b" ; "c" }', + ), + # Identity on maps + ('map_id.tz', '{}', '{ Elt 0 1 }', '{ Elt 0 1 }'), + ('map_id.tz', '{}', '{ Elt 0 0 }', '{ Elt 0 0 }'), + ( + 'map_id.tz', + '{}', + '{ Elt 0 0 ; Elt 3 4 }', + '{ Elt 0 0 ; Elt 3 4 }', + ), + # Memberships in maps + ( + 'map_mem_nat.tz', + '(Pair { Elt 0 1 } None)', + '1', + '(Pair { Elt 0 1 } (Some False))', + ), + ('map_mem_nat.tz', '(Pair {} None)', '1', '(Pair {} (Some False))'), + ( + 'map_mem_nat.tz', + '(Pair { Elt 1 0 } None)', + '1', + '(Pair { Elt 1 0 } (Some True))', + ), + ( + 'map_mem_nat.tz', + '(Pair { Elt 1 4 ; Elt 2 11 } None)', + '1', + '(Pair { Elt 1 4 ; Elt 2 11 } (Some True))', + ), + ( + 'map_mem_nat.tz', + '(Pair { Elt 1 4 ; Elt 2 11 } None)', + '2', + '(Pair { Elt 1 4 ; Elt 2 11 } (Some True))', + ), + ( + 'map_mem_nat.tz', + '(Pair { Elt 1 4 ; Elt 2 11 } None)', + '3', + '(Pair { Elt 1 4 ; Elt 2 11 } (Some False))', + ), + ( + 'map_mem_string.tz', + '(Pair { Elt "foo" 1 } None)', + '"bar"', + '(Pair { Elt "foo" 1 } (Some False))', + ), + ( + 'map_mem_string.tz', + '(Pair {} None)', + '"bar"', + '(Pair {} (Some False))', + ), + ( + 'map_mem_string.tz', + '(Pair { Elt "foo" 0 } None)', + '"foo"', + '(Pair { Elt "foo" 0 } (Some True))', + ), + ( + 'map_mem_string.tz', + '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)', + '"foo"', + '(Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True))', + ), + ( + 'map_mem_string.tz', + '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)', + '"bar"', + '(Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True))', + ), + ( + 'map_mem_string.tz', + '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)', + '"baz"', + '(Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False))', + ), + # Mapping over maps + ('map_map.tz', '{}', '10', '{}'), + ('map_map.tz', '{ Elt "foo" 1 }', '10', '{ Elt "foo" 11 }'), + ( + 'map_map.tz', + '{ Elt "bar" 5 ; Elt "foo" 1 }', + '15', + '{ Elt "bar" 20 ; Elt "foo" 16 }', + ), + # Memberships in big maps + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 0 1 } None)', + '1', + '(Pair 0 (Some False))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair {} None)', + '1', + '(Pair 0 (Some False))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 1 0 } None)', + '1', + '(Pair 0 (Some True))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 1 4 ; Elt 2 11 } None)', + '1', + '(Pair 0 (Some True))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 1 4 ; Elt 2 11 } None)', + '2', + '(Pair 0 (Some True))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 1 4 ; Elt 2 11 } None)', + '3', + '(Pair 0 (Some False))', + ), + ( + 'big_map_mem_string.tz', + '(Pair { Elt "foo" 1 } None)', + '"bar"', + '(Pair 0 (Some False))', + ), + ( + 'big_map_mem_string.tz', + '(Pair {} None)', + '"bar"', + '(Pair 0 (Some False))', + ), + ( + 'big_map_mem_string.tz', + '(Pair { Elt "foo" 0 } None)', + '"foo"', + '(Pair 0 (Some True))', + ), + ( + 'big_map_mem_string.tz', + '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)', + '"foo"', + '(Pair 0 (Some True))', + ), + ( + 'big_map_mem_string.tz', + '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)', + '"bar"', + '(Pair 0 (Some True))', + ), + ( + 'big_map_mem_string.tz', + '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)', + '"baz"', + '(Pair 0 (Some False))', + ), + # Memberships in big maps + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 0 1 } None)', + '1', + '(Pair 0 (Some False))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair {} None)', + '1', + '(Pair 0 (Some False))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 1 0 } None)', + '1', + '(Pair 0 (Some True))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 1 4 ; Elt 2 11 } None)', + '1', + '(Pair 0 (Some True))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 1 4 ; Elt 2 11 } None)', + '2', + '(Pair 0 (Some True))', + ), + ( + 'big_map_mem_nat.tz', + '(Pair { Elt 1 4 ; Elt 2 11 } None)', + '3', + '(Pair 0 (Some False))', + ), + # Identity on sets + ('set_id.tz', '{}', '{ "a" ; "b" ; "c" }', '{ "a" ; "b" ; "c" }'), + ('set_id.tz', '{}', '{}', '{}'), + ('set_id.tz', '{}', '{ "asdf" ; "bcde" }', '{ "asdf" ; "bcde" }'), + # List concat + ('list_concat.tz', '"abc"', '{ "d" ; "e" ; "f" }', '"abcdef"'), + ('list_concat.tz', '"abc"', '{}', '"abc"'), + ( + 'list_concat_bytes.tz', + '0x00ab', + '{ 0xcd ; 0xef ; 0x00 }', + '0x00abcdef00', + ), + ( + 'list_concat_bytes.tz', + '0x', + '{ 0x00 ; 0x11 ; 0x00 }', + '0x001100', + ), + ('list_concat_bytes.tz', '0xabcd', '{}', '0xabcd'), + ('list_concat_bytes.tz', '0x', '{}', '0x'), + # List iter + ('list_iter.tz', '0', '{ 10 ; 2 ; 1 }', '20'), + ('list_iter.tz', '0', '{ 3 ; 6 ; 9 }', '162'), + # List size + ('list_size.tz', '111', '{}', '0'), + ('list_size.tz', '111', '{ 1 }', '1'), + ('list_size.tz', '111', '{ 1 ; 2 ; 3 }', '3'), + ('list_size.tz', '111', '{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }', '6'), + # Set member -- set is in storage + ( + 'set_member.tz', + '(Pair {} None)', + '"Hi"', + '(Pair {} (Some False))', + ), + ( + 'set_member.tz', + '(Pair { "Hi" } None)', + '"Hi"', + '(Pair { "Hi" } (Some True))', + ), + ( + 'set_member.tz', + '(Pair { "Hello" ; "World" } None)', + '""', + '(Pair { "Hello" ; "World" } (Some False))', + ), + # Set size + ('set_size.tz', '111', '{}', '0'), + ('set_size.tz', '111', '{ 1 }', '1'), + ('set_size.tz', '111', '{ 1 ; 2 ; 3 }', '3'), + ('set_size.tz', '111', '{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }', '6'), + # Set iter + ('set_iter.tz', '111', '{}', '0'), + ('set_iter.tz', '111', '{ 1 }', '1'), + ('set_iter.tz', '111', '{ -100 ; 1 ; 2 ; 3 }', '-94'), + # Map size + ('map_size.tz', '111', '{}', '0'), + ('map_size.tz', '111', '{ Elt "a" 1 }', '1'), + ( + 'map_size.tz', + '111', + '{ Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 }', + '3', + ), + ( + 'map_size.tz', + '111', + '{ Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 ; \ + Elt "d" 4 ; Elt "e" 5 ; Elt "f" 6 }', + '6', + ), + # Contains all elements -- does the second list contain + # all of the same elements as the first one? I'm ignoring + # element multiplicity + ('contains_all.tz', 'None', '(Pair {} {})', '(Some True)'), + ( + 'contains_all.tz', + 'None', + '(Pair { "c" } { "B" })', + '(Some False)', + ), + ( + 'contains_all.tz', + 'None', + '(Pair { "A" } { "B" })', + '(Some False)', + ), + ( + 'contains_all.tz', + 'None', + '(Pair { "B" } { "B" })', + '(Some True)', + ), + ( + 'contains_all.tz', + 'None', + '(Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" })', + '(Some True)', + ), + ( + 'contains_all.tz', + 'None', + '(Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" })', + '(Some True)', + ), + # Concatenate the string in storage with all strings in + # the given list + ('concat_hello.tz', '{}', '{ "World!" }', '{ "Hello World!" }'), + ('concat_hello.tz', '{}', '{}', '{}'), + ( + 'concat_hello.tz', + '{}', + '{ "test1" ; "test2" }', + '{ "Hello test1" ; "Hello test2" }', + ), + # Create an empty map and add a string to it + ('empty_map.tz', '{}', 'Unit', '{ Elt "hello" "world" }'), + # Get the value stored at the given key in the map + ( + 'get_map_value.tz', + '(Pair None { Elt "hello" "hi" })', + '"hello"', + '(Pair (Some "hi") { Elt "hello" "hi" })', + ), + ( + 'get_map_value.tz', + '(Pair None { Elt "hello" "hi" })', + '""', + '(Pair None { Elt "hello" "hi" })', + ), + ( + 'get_map_value.tz', + '(Pair None { Elt "1" "one" ; \ + Elt "2" "two" })', + '"1"', + '(Pair (Some "one") { Elt "1" "one" ; Elt "2" "two" })', + ), + # Get and update the value stored at the given key in the map + ( + 'get_and_update_map.tz', + '(Pair None {})', + '"hello"', + '(Pair None {})', + ), + ( + 'get_and_update_map.tz', + '(Pair (Some 4) {})', + '"hello"', + '(Pair None { Elt "hello" 4 })', + ), + ( + 'get_and_update_map.tz', + '(Pair None { Elt "hello" 4 })', + '"hello"', + '(Pair (Some 4) {})', + ), + ( + 'get_and_update_map.tz', + '(Pair (Some 5) { Elt "hello" 4 })', + '"hello"', + '(Pair (Some 4) { Elt "hello" 5 })', + ), + ( + 'get_and_update_map.tz', + '(Pair (Some 5) { Elt "hello" 4 })', + '"hi"', + '(Pair None { Elt "hello" 4 ; Elt "hi" 5 })', + ), + ( + 'get_and_update_map.tz', + '(Pair None { Elt "1" 1 ; \ + Elt "2" 2 })', + '"1"', + '(Pair (Some 1) { Elt "2" 2 })', + ), + ( + 'get_and_update_map.tz', + '(Pair None { Elt "1" 1 ; \ + Elt "2" 2 })', + '"1"', + '(Pair (Some 1) { Elt "2" 2 })', + ), + # Map iter + ( + 'map_iter.tz', + '(Pair 0 0)', + '{ Elt 0 100 ; Elt 2 100 }', + '(Pair 2 200)', + ), + ( + 'map_iter.tz', + '(Pair 0 0)', + '{ Elt 1 1 ; Elt 2 100 }', + '(Pair 3 101)', + ), + # Return True if True branch of if was taken and False otherwise + ('if.tz', 'None', 'True', '(Some True)'), + ('if.tz', 'None', 'False', '(Some False)'), + # Generate a pair of or types + ('left_right.tz', '(Left "X")', '(Left True)', '(Right True)'), + ('left_right.tz', '(Left "X")', '(Right "a")', '(Left "a")'), + # Reverse a list + ('reverse_loop.tz', '{""}', '{}', '{}'), + ( + 'reverse_loop.tz', + '{""}', + '{ "c" ; "b" ; "a" }', + '{ "a" ; "b" ; "c" }', + ), + # Exec concat contract + ('exec_concat.tz', '"?"', '""', '"_abc"'), + ('exec_concat.tz', '"?"', '"test"', '"test_abc"'), + # Get the current balance of the contract + ('balance.tz', '111', 'Unit', '4000000000000'), + # Get the current level of the block + # Test the produced variable annotation + ('level.tz', '111', 'Unit', '1'), + # Test addition and subtraction on tez + ( + 'tez_add_sub.tz', + 'None', + '(Pair 2000000 1000000)', + '(Some (Pair 3000000 1000000))', + ), + ( + 'tez_add_sub.tz', + 'None', + '(Pair 2310000 1010000)', + '(Some (Pair 3320000 1300000))', + ), + # Test various additions + ('add.tz', 'Unit', 'Unit', 'Unit'), + # Test ABS + ('abs.tz', 'Unit', '12039123919239192312931', 'Unit'), + ('abs.tz', 'Unit', '0', 'Unit'), + ('abs.tz', 'Unit', '948', 'Unit'), + # Test INT + ('int.tz', 'None', '0', '(Some 0)'), + ('int.tz', 'None', '1', '(Some 1)'), + ('int.tz', 'None', '9999', '(Some 9999)'), + # Test DIP + ('dip.tz', '(Pair 0 0)', '(Pair 15 9)', '(Pair 15 24)'), + ('dip.tz', '(Pair 0 0)', '(Pair 1 1)', '(Pair 1 2)'), + # Test get first element of list + ('first.tz', '111', '{ 1 ; 2 ; 3 ; 4 }', '1'), + ('first.tz', '111', '{ 4 }', '4'), + # Hash input string + # Test assumed to be correct -- hash is based on encoding of AST + ( + 'hash_string.tz', + '0x00', + '"abcdefg"', + '0x46fdbcb4ea4eadad5615c' + + 'daa17d67f783e01e21149ce2b27de497600b4cd8f4e', + ), + ( + 'hash_string.tz', + '0x00', + '"12345"', + '0xb4c26c20de52a4eaf0d8a34' + + '0db47ad8cb1e74049570859c9a9a3952b204c772f', + ), + # IF_SOME + ('if_some.tz', '"?"', '(Some "hello")', '"hello"'), + ('if_some.tz', '"?"', 'None', '""'), + # Tests the SET_CAR and SET_CDR instructions + ('set_car.tz', '(Pair "hello" 0)', '"world"', '(Pair "world" 0)'), + ('set_car.tz', '(Pair "hello" 0)', '"abc"', '(Pair "abc" 0)'), + ('set_car.tz', '(Pair "hello" 0)', '""', '(Pair "" 0)'), + ('set_cdr.tz', '(Pair "hello" 0)', '1', '(Pair "hello" 1)'), + ('set_cdr.tz', '(Pair "hello" 500)', '3', '(Pair "hello" 3)'), + ('set_cdr.tz', '(Pair "hello" 7)', '100', '(Pair "hello" 100)'), + # Convert a public key to a public key hash + ( + 'hash_key.tz', + 'None', + '"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"', + '(Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx")', + ), + ( + 'hash_key.tz', + 'None', + '"edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTawUPqR8vZTAMcx61ES"', + '(Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k")', + ), + # Test timestamp operations + ( + 'add_timestamp_delta.tz', + 'None', + '(Pair 100 100)', + '(Some "1970-01-01T00:03:20Z")', + ), + ( + 'add_timestamp_delta.tz', + 'None', + '(Pair 100 -100)', + '(Some "1970-01-01T00:00:00Z")', + ), + ( + 'add_timestamp_delta.tz', + 'None', + '(Pair "1970-01-01T00:00:00Z" 0)', + '(Some "1970-01-01T00:00:00Z")', + ), + ( + 'add_delta_timestamp.tz', + 'None', + '(Pair 100 100)', + '(Some "1970-01-01T00:03:20Z")', + ), + ( + 'add_delta_timestamp.tz', + 'None', + '(Pair -100 100)', + '(Some "1970-01-01T00:00:00Z")', + ), + ( + 'add_delta_timestamp.tz', + 'None', + '(Pair 0 "1970-01-01T00:00:00Z")', + '(Some "1970-01-01T00:00:00Z")', + ), + ( + 'sub_timestamp_delta.tz', + '111', + '(Pair 100 100)', + '"1970-01-01T00:00:00Z"', + ), + ( + 'sub_timestamp_delta.tz', + '111', + '(Pair 100 -100)', + '"1970-01-01T00:03:20Z"', + ), + ( + 'sub_timestamp_delta.tz', + '111', + '(Pair 100 2000000000000000000)', + '-1999999999999999900', + ), + ('diff_timestamps.tz', '111', '(Pair 0 0)', '0'), + ('diff_timestamps.tz', '111', '(Pair 0 1)', '-1'), + ('diff_timestamps.tz', '111', '(Pair 1 0)', '1'), + ( + 'diff_timestamps.tz', + '111', + '(Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z")', + '200', + ), + # Test pack/unpack + ( + 'packunpack_rev.tz', + 'Unit', + '(Pair -1 (Pair 1 (Pair "foobar" (Pair 0x00AABBCC (Pair 1000 ' + + '(Pair False (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ' + + '(Pair "2019-09-09T08:35:33Z" ' + + '"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"))))))))', + 'Unit', + ), + ( + 'packunpack_rev.tz', + 'Unit', + '(Pair -1 (Pair 1 (Pair "foobar" (Pair 0x00AABBCC (Pair 1000 ' + + '(Pair False (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ' + + '(Pair "2019-09-09T08:35:33Z" ' + + '"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"))))))))', + 'Unit', + ), + ( + 'packunpack_rev_cty.tz', + 'Unit', + '(Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9' + + 'sDVC9yav" (Pair Unit (Pair "edsigthTzJ8X7MPmNeEwybRAv' + + 'dxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8' + + 'V2w8ayB5dMJzrYCHhD8C7" (Pair (Some "edsigthTzJ8X7MPmN' + + 'eEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5' + + 'CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") (Pair { Unit } (Pair' + + ' { True } (Pair (Pair 19 10) (Pair (Left "tz1cxcwwnz' + + 'ENRdhe2Kb8ZdTrdNy4bFNyScx5") (Pair { Elt 0 "foo" ; El' + + 't 1 "bar" } { PACK } )))))))))', + 'Unit', + ), + ( + 'packunpack_rev_cty.tz', + 'Unit', + '(Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9' + + 'sDVC9yav" (Pair Unit (Pair "edsigthTzJ8X7MPmNeEwybRAv' + + 'dxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8' + + 'V2w8ayB5dMJzrYCHhD8C7" (Pair None (Pair { } (Pair {' + + ' } (Pair (Pair 40 -10) (Pair (Right "2019-09-09T08:' + + '35:33Z") (Pair { } { DUP ; DROP ; PACK } )))))))))', + 'Unit', + ), + # Test EDIV on nat and int + ( + 'ediv.tz', + '(Pair None None None None)', + '(Pair 10 -3)', + '(Pair (Some (Pair -3 1)) (Some (Pair 3 1)) ' + + '(Some (Pair -3 1)) (Some (Pair 3 1)))', + ), + ( + 'ediv.tz', + '(Pair None None None None)', + '(Pair 10 0)', + '(Pair None None None None)', + ), + ( + 'ediv.tz', + '(Pair None None None None)', + '(Pair -8 2)', + '(Pair (Some (Pair -4 0)) (Some (Pair -4 0)) ' + + '(Some (Pair 4 0)) (Some (Pair 4 0)))', + ), + # Test EDIV on mutez + ( + 'ediv_mutez.tz', + '(Left None)', + '(Pair 10 (Left 10))', + '(Left (Some (Pair 1 0)))', + ), + ( + 'ediv_mutez.tz', + '(Left None)', + '(Pair 10 (Left 3))', + '(Left (Some (Pair 3 1)))', + ), + ( + 'ediv_mutez.tz', + '(Left None)', + '(Pair 10 (Left 0))', + '(Left None)', + ), + ( + 'ediv_mutez.tz', + '(Left None)', + '(Pair 10 (Right 10))', + '(Right (Some (Pair 1 0)))', + ), + ( + 'ediv_mutez.tz', + '(Left None)', + '(Pair 10 (Right 3))', + '(Right (Some (Pair 3 1)))', + ), + ( + 'ediv_mutez.tz', + '(Left None)', + '(Pair 10 (Right 0))', + '(Right None)', + ), + ( + 'ediv_mutez.tz', + '(Left None)', + '(Pair 5 (Right 10))', + '(Right (Some (Pair 0 5)))', + ), + # Test compare + ('compare.tz', 'Unit', 'Unit', 'Unit'), + # Test comparison combinators: + # GT, GE, LT, LE, NEQ, EQ + ( + 'comparisons.tz', + '{}', + '{ -9999999; -1 ; 0 ; 1 ; 9999999 }', + '{ ' + '{ False ; False ; False ; True ; True } ;' + "\n" + ' { False ; False ; True ; True ; True } ;' + "\n" + ' { True ; True ; False ; False ; False } ;' + "\n" + ' { True ; True ; True ; False ; False } ;' + "\n" + ' { True ; True ; False ; True ; True } ;' + "\n" + ' { False ; False ; True ; False ; False }' + ' }', + ), + # Test ADDRESS + ( + 'address.tz', + 'None', + '"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"', + '(Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5")', + ), + # Test (CONTRACT unit) + ( + 'contract.tz', + 'Unit', + '"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"', + 'Unit', + ), + # Test create_contract + ( + 'create_contract.tz', + 'None', + 'Unit', + '(Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm")', + ), + # Test multiplication - success case (no overflow) + # Failure case is tested in m̀ul_overflow.tz + ('mul.tz', 'Unit', 'Unit', 'Unit'), + # Test NEG + ('neg.tz', '0', '(Left 2)', '-2'), + ('neg.tz', '0', '(Right 2)', '-2'), + ('neg.tz', '0', '(Left 0)', '0'), + ('neg.tz', '0', '(Right 0)', '0'), + ('neg.tz', '0', '(Left -2)', '2'), + # Test DIGN, DUGN, DROPN, DIPN + ('dign.tz', '0', '(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)', '5'), + ('dugn.tz', '0', '(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)', '1'), + ('dropn.tz', '0', '(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)', '5'), + ('dipn.tz', '0', '(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)', '6'), + # Test DIGN 17 times. + ( + 'dig_eq.tz', + 'Unit', + '(Pair 17 (Pair 16 (Pair 15 (Pair 14 (Pair 13 (Pair 12' + + ' (Pair 11 (Pair 10 (Pair 9 (Pair 8 (Pair 7 (Pair 6 (P' + + 'air 5 (Pair 4 (Pair 3 (Pair 2 1))))))))))))))))', + 'Unit', + ), + ( + 'dig_eq.tz', + 'Unit', + '(Pair 2 (Pair 3 (Pair 12 (Pair 16 (Pair 10 (Pair 14 (' + + 'Pair 19 (Pair 9 (Pair 18 (Pair 6 (Pair 8 (Pair 11 (Pa' + + 'ir 4 (Pair 13 (Pair 15 (Pair 5 1))))))))))))))))', + 'Unit', + ), + # Test Partial Exec + ('pexec.tz', '14', '38', '52'), + ('pexec_2.tz', "{ 0 ; 1 ; 2 ; 3}", '4', "{ 0 ; 7 ; 14 ; 21 }"), + # Test CHAIN_ID + ('chain_id_store.tz', 'None', 'Unit', '(Some "NetXdQprcVkpaWU")'), + ( + 'chain_id_store.tz', + '(Some 0x7a06a770)', + 'Unit', + '(Some "NetXdQprcVkpaWU")', + ), + ( + 'chain_id_store.tz', + '(Some "NetXdQprcVkpaWU")', + 'Unit', + '(Some "NetXdQprcVkpaWU")', + ), + # Test SELF + ('self_with_entrypoint.tz', 'Unit', 'Left (Left 0)', 'Unit'), + ('self_with_default_entrypoint.tz', 'Unit', 'Unit', 'Unit'), + # Test SELF_ADDRESS + ('self_address.tz', 'Unit', 'Unit', 'Unit'), + # Test UNPAIR + ('unpair.tz', 'Unit', 'Unit', 'Unit'), + # Test VOTING_POWER + ( + 'voting_power.tz', + '(Pair 0 0)', + f'"{PUBLIC_KEY}"', + '(Pair 500 2500)', + ), + # Test KECCAK + ( + 'keccak.tz', + 'None', + f'0x{b"Hello, world!".hex()}', + '(Some 0xb6e16d27ac5ab427a7f68900ac5559ce2' + + '72dc6c37c82b3e052246c82244c50e4)', + ), + # Test SHA3 + ( + 'sha3.tz', + 'None', + f'0x{b"Hello, world!".hex()}', + '(Some 0xf345a219da005ebe9c1a1eaad97bbf38' + + 'a10c8473e41d0af7fb617caa0c6aa722)', + ), + # Test COMBs + ('comb.tz', '(Pair 0 0 0)', 'Unit', '(Pair 1 2 3)'), + ('uncomb.tz', '0', '(Pair 1 4 2)', '142'), + ('comb-get.tz', 'Unit', '(Pair 1 4 2 Unit)', 'Unit'), + ('comb-set.tz', '(Pair 1 4 2 Unit)', 'Unit', '(Pair 2 12 8 Unit)'), + ( + 'comb-set-2.tz', + 'None', + '(Pair 1 4 2 Unit)', + '(Some (Pair 2 4 "toto" 0x01))', + ), + # Test DUP n + ('dup-n.tz', 'Unit', 'Unit', 'Unit'), + # Test Sapling + ('sapling_empty_state.tz', '{}', 'Unit', '0'), + # Test building Fr element from nat. + # The initial storage is dropped then any value is valid. + # Random values can be generated using the following OCaml program. + # let r = Bls12_381.Fr.(random ()) in + # let x = Bls12_381.Fr.random () in + # Printf.printf "Param = (Pair %s 0x%s). Result = 0x%s" + # (Bls12_381.Fr.to_string r) + # (Hex.(show (of_bytes (Bls12_381.Fr.to_bytes x)))) + # (Hex.(show (of_bytes (Bls12_381.Fr.(to_bytes (mul r x)))))) + ( + 'bls12_381_fr_z_nat.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '0', + '0x00000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_fr_z_nat.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '1', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + # The natural is 1 in Fr. + ( + 'bls12_381_fr_z_nat.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '524358751751261904794477405081859658376905525005276378226036' + '58699938581184514', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_fr_z_nat.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '2', + '0x02000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_fr_z_nat.tz', + '0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c' + + '5401f', + '3364491663033484423912034843462646864953418677080980279259699' + + '6408934105684394', + '0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca91' + + '8a221', + ), + ( + 'bls12_381_fr_z_nat.tz', + '0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfc' + + 'dbe3f', + '2262028481792278490256467246991799299632821112798447289749169' + + '8543785655336309', + '0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe6' + + '77c62', + ), + ( + 'bls12_381_fr_z_nat.tz', + '0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7' + + 'fcf2d', + '1718009307279455880617703583439793220591757728848373965251048' + + '2486858834123369', + '0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddec' + + 'bf221', + ), + # Same than previous one, but we added the order to the natural to + # verify the modulo is computed correctly and the multiplication + # computation does not fail. + ( + 'bls12_381_fr_z_nat.tz', + '0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7' + + 'fcf2d', + '69615968247920749285624776342583898043608129789011377475114141' + + '186797415307882', + '0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddec' + + 'bf221', + ), + # Test with (positive and negative) integers. + ( + 'bls12_381_fr_z_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '0', + '0x00000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_fr_z_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '1', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_fr_z_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '524358751751261904794477405081859658376905525005276378226036' + '58699938581184514', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_fr_z_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '2', + '0x02000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_fr_z_int.tz', + '0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c' + + '5401f', + '3364491663033484423912034843462646864953418677080980279259699' + + '6408934105684394', + '0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca91' + + '8a221', + ), + ( + 'bls12_381_fr_z_int.tz', + '0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfc' + + 'dbe3f', + '2262028481792278490256467246991799299632821112798447289749169' + + '8543785655336309', + '0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe6' + + '77c62', + ), + ( + 'bls12_381_fr_z_int.tz', + '0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7' + + 'fcf2d', + '1718009307279455880617703583439793220591757728848373965251048' + + '2486858834123369', + '0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddec' + + 'bf221', + ), + # Same than previous one, but we added the order to the natural to + # verify the modulo is computed correctly and the multiplication + # computation does not fail. + ( + 'bls12_381_fr_z_int.tz', + '0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7' + + 'fcf2d', + '69615968247920749285624776342583898043608129789011377475114141' + + '186797415307882', + '0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddec' + + 'bf221', + ), + ( + 'bls12_381_fr_z_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '-1', + '0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953' + + 'a7ed73', + ), + ( + 'bls12_381_fr_z_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '-42', + '0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a' + + '7ed73', + ), + # Test building Fr element from nat. + # The initial storage is dropped then any value is valid. + # Random values can be generated using the following OCaml program. + # let r = Bls12_381.Fr.(random ()) in + # let x = Bls12_381.Fr.random () in + # Printf.printf "Param = (Pair %s 0x%s). Result = 0x%s" + # (Bls12_381.Fr.to_string r) + # (Hex.(show (of_bytes (Bls12_381.Fr.to_bytes x)))) + # (Hex.(show (of_bytes (Bls12_381.Fr.(to_bytes (mul r x)))))) + ( + 'bls12_381_z_fr_nat.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '0', + '0x00000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_z_fr_nat.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '1', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + # The natural is 1 in Fr. + ( + 'bls12_381_z_fr_nat.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '524358751751261904794477405081859658376905525005276378226036' + '58699938581184514', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_z_fr_nat.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '2', + '0x02000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_z_fr_nat.tz', + '0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c' + + '5401f', + '3364491663033484423912034843462646864953418677080980279259699' + + '6408934105684394', + '0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca91' + + '8a221', + ), + ( + 'bls12_381_z_fr_nat.tz', + '0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfc' + + 'dbe3f', + '2262028481792278490256467246991799299632821112798447289749169' + + '8543785655336309', + '0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe6' + + '77c62', + ), + ( + 'bls12_381_z_fr_nat.tz', + '0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7' + + 'fcf2d', + '1718009307279455880617703583439793220591757728848373965251048' + + '2486858834123369', + '0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddec' + + 'bf221', + ), + # Same than previous one, but we added the order to the natural to + # verify the modulo is computed correctly and the multiplication + # computation does not fail. + ( + 'bls12_381_z_fr_nat.tz', + '0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7' + + 'fcf2d', + '69615968247920749285624776342583898043608129789011377475114141' + + '186797415307882', + '0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddec' + + 'bf221', + ), + # Test with (positive and negative) integers. + ( + 'bls12_381_z_fr_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '0', + '0x00000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_z_fr_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '1', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_z_fr_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '524358751751261904794477405081859658376905525005276378226036' + '58699938581184514', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_z_fr_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '2', + '0x02000000000000000000000000000000000000000000000000000000000' + + '00000', + ), + ( + 'bls12_381_z_fr_int.tz', + '0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c' + + '5401f', + '3364491663033484423912034843462646864953418677080980279259699' + + '6408934105684394', + '0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca91' + + '8a221', + ), + ( + 'bls12_381_z_fr_int.tz', + '0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfc' + + 'dbe3f', + '2262028481792278490256467246991799299632821112798447289749169' + + '8543785655336309', + '0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe6' + + '77c62', + ), + ( + 'bls12_381_z_fr_int.tz', + '0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7' + + 'fcf2d', + '1718009307279455880617703583439793220591757728848373965251048' + + '2486858834123369', + '0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddec' + + 'bf221', + ), + ( + 'bls12_381_z_fr_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '-1', + '0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953' + + 'a7ed73', + ), + ( + 'bls12_381_z_fr_int.tz', + '0x01000000000000000000000000000000000000000000000000000000000' + + '00000', + '-42', + '0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a' + + '7ed73', + ), + # Same than previous one, but we added the order to the natural to + # verify the modulo is computed correctly and the multiplication + # computation does not fail. + ( + 'bls12_381_z_fr_int.tz', + '0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7' + + 'fcf2d', + '69615968247920749285624776342583898043608129789011377475114141' + + '186797415307882', + '0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddec' + + 'bf221', + ), + # Test Fr bytes can be pushed without being padded + ( + 'add_bls12_381_fr.tz', + 'None', + 'Pair 0x00 0x00', + '(Some 0x000000000000000000000000000000000000000000000000000000' + + '0000000000)', + ), + ( + 'add_bls12_381_fr.tz', + 'None', + 'Pair 0x01 0x00', + '(Some 0x010000000000000000000000000000000000000000000000000000' + + '0000000000)', + ), + ( + 'add_bls12_381_fr.tz', + 'None', + 'Pair 0x010000 0x00', + '(Some 0x010000000000000000000000000000000000000000000000000000' + + '0000000000)', + ), + ( + 'add_bls12_381_fr.tz', + 'None', + 'Pair 0x010000 0x010000', + '(Some 0x020000000000000000000000000000000000000000000000000000' + + '0000000000)', + ), + ( + 'bls12_381_fr_push_bytes_not_padded.tz', + 'None', + 'Unit', + '(Some 0x000000000000000000000000000000000000000000000000000000' + + '0000000000)', + ), + ( + 'bls12_381_fr_push_nat.tz', + 'None', + 'Unit', + '(Some 0x100000000000000000000000000000000000000000000000000000' + + '0000000000)', + ), + ('bls12_381_fr_to_int.tz', '0', '0x00', '0'), + ('bls12_381_fr_to_int.tz', '0', '0x01', '1'), + # Generated using + # let r = Bls12_381.Fr.(random ()) in + # Printf.printf "%s = 0x%s" + # (Bls12_381.Fr.to_string r) + # (Hex.(show (of_bytes (Bls12_381.Fr.to_bytes r)))) + ( + 'bls12_381_fr_to_int.tz', + '0', + '0x28db8e57af88d9576acd181b89f24e50a89a6423f939026ed91349fc9' + + 'af16c27', + '1783268807701357777652478449446472851821391321341286660405373' + + '5695200962927400', + ), + ( + 'bls12_381_fr_to_int.tz', + '0', + '0xb9e8abf8dc324a010007addde986fe0f7c81fab16d26819d0534b7691c' + + '0b0719', + '1132026582925658583078152196614952946047676740821044523890286' + + '9222031333517497', + ), + # Mutez -> Fr + ( + 'mutez_to_bls12_381_fr.tz', + '0x02', + '16', + '0x100000000000000000000000000000000000000000000000000000000' + + '0000000', + ), + # # would fail if trying to PACK mutez and UNPACK to Fr + ( + 'mutez_to_bls12_381_fr.tz', + '0x00', + '257', + '0x010100000000000000000000000000000000000000000000000000000' + + '0000000', + ), + # Fr -> Mutez + ('bls12_381_fr_to_mutez.tz', '0', '0x10', '16'), + ], + ) + def test_contract_input_output( + self, + client_regtest: ClientRegression, + contract: str, + param: str, + storage: str, + expected: str, + ): + client = client_regtest + assert contract.endswith( + '.tz' + ), "test contract should have .tz extension" + contract = path.join(OPCODES_CONTRACT_PATH, contract) + run_script_res = client.run_script( + contract, param, storage, trace_stack=True + ) + assert run_script_res.storage == expected + + @pytest.mark.parametrize("balance", [0, 0.000001, 0.5, 1, 5, 1000, 8e12]) + def test_balance(self, client_regtest: ClientRegression, balance: float): + client = client_regtest + contract = 'balance.tz' + contract = path.join(OPCODES_CONTRACT_PATH, contract) + run_script_res = client.run_script( + contract, '0', 'Unit', balance=balance, trace_stack=True + ) + assert run_script_res.storage == str(int(1000000 * balance)) + + @pytest.mark.parametrize( + "contract,param,storage,expected,big_map_diff", + [ # FORMAT: assert_output contract_file storage input expected_result + # expected_diffs + # Get the value stored at the given key in the big map + ( + 'get_big_map_value.tz', + '(Pair { Elt "hello" "hi" } None)', + '"hello"', + '(Pair 0 (Some "hi"))', + [ + ["New map(0) of type (big_map string string)"], + ['Set map(0)["hello"] to "hi"'], + ], + ), + ( + 'get_big_map_value.tz', + '(Pair { Elt "hello" "hi" } None)', + '""', + '(Pair 0 None)', + [ + ["New map(0) of type (big_map string string)"], + ['Set map(0)["hello"] to "hi"'], + ], + ), + ( + 'get_big_map_value.tz', + '(Pair { Elt "1" "one" ; Elt "2" "two" } None)', + '"1"', + '(Pair 0 (Some "one"))', + [ + ["New map(0) of type (big_map string string)"], + ['Set map(0)["2"] to "two"'], + ['Set map(0)["1"] to "one"'], + ], + ), + # Test updating big maps + ( + 'update_big_map.tz', + '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)', + '{}', + '(Pair 0 Unit)', + [ + ["New map(0) of type (big_map string string)"], + ['Set map(0)["2"] to "two"'], + ['Set map(0)["1"] to "one"'], + ], + ), + ( + 'update_big_map.tz', + '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)', + '{ Elt "1" (Some "two") }', + '(Pair 0 Unit)', + [ + ["New map(0) of type (big_map string string)"], + ['Set map(0)["2"] to "two"'], + ['Set map(0)["1"] to "two"'], + ], + ), + ( + 'update_big_map.tz', + '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)', + '{ Elt "3" (Some "three") }', + '(Pair 0 Unit)', + [ + ["New map(0) of type (big_map string string)"], + ['Set map(0)["2"] to "two"'], + ['Set map(0)["3"] to "three"'], + ['Set map(0)["1"] to "one"'], + ], + ), + ( + 'update_big_map.tz', + '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)', + '{ Elt "3" None }', + '(Pair 0 Unit)', + [ + ["New map(0) of type (big_map string string)"], + ['Set map(0)["2"] to "two"'], + ['Unset map(0)["3"]'], + ['Set map(0)["1"] to "one"'], + ], + ), + ( + 'update_big_map.tz', + '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)', + '{ Elt "2" None }', + '(Pair 0 Unit)', + [ + ["New map(0) of type (big_map string string)"], + ['Unset map(0)["2"]'], + ['Set map(0)["1"] to "one"'], + ], + ), + ( + 'update_big_map.tz', + '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)', + '{ Elt "1" (Some "two") }', + '(Pair 0 Unit)', + [ + ["New map(0) of type (big_map string string)"], + ['Set map(0)["2"] to "two"'], + ['Set map(0)["1"] to "two"'], + ], + ), + # test the GET_AND_UPDATE instruction on big maps + # Get and update the value stored at the given key in the map + ( + 'get_and_update_big_map.tz', + '(Pair None {})', + '"hello"', + '(Pair None 0)', + [ + ["New map(0) of type (big_map string nat)"], + ['Unset map(0)["hello"]'], + ], + ), + ( + 'get_and_update_big_map.tz', + '(Pair (Some 4) {})', + '"hello"', + '(Pair None 0)', + [ + ["New map(0) of type (big_map string nat)"], + ['Set map(0)["hello"] to 4'], + ], + ), + ( + 'get_and_update_big_map.tz', + '(Pair None { Elt "hello" 4 })', + '"hello"', + '(Pair (Some 4) 0)', + [ + ["New map(0) of type (big_map string nat)"], + ['Unset map(0)["hello"]'], + ], + ), + ( + 'get_and_update_big_map.tz', + '(Pair (Some 5) { Elt "hello" 4 })', + '"hello"', + '(Pair (Some 4) 0)', + [ + ["New map(0) of type (big_map string nat)"], + ['Set map(0)["hello"] to 5'], + ], + ), + ( + 'get_and_update_big_map.tz', + '(Pair (Some 5) { Elt "hello" 4 })', + '"hi"', + '(Pair None 0)', + [ + ["New map(0) of type (big_map string nat)"], + ['Set map(0)["hello"] to 4'], + ['Set map(0)["hi"] to 5'], + ], + ), + ( + 'get_and_update_big_map.tz', + '(Pair None { Elt "1" 1 ; \ + Elt "2" 2 })', + '"1"', + '(Pair (Some 1) 0)', + [ + ["New map(0) of type (big_map string nat)"], + ['Set map(0)["2"] to 2'], + ['Unset map(0)["1"]'], + ], + ), + ( + 'get_and_update_big_map.tz', + '(Pair None { Elt "1" 1 ; \ + Elt "2" 2 })', + '"1"', + '(Pair (Some 1) 0)', + [ + ["New map(0) of type (big_map string nat)"], + ['Set map(0)["2"] to 2'], + ['Unset map(0)["1"]'], + ], + ), + ], + ) + def test__big_map_contract_io( + self, + client_regtest: ClientRegression, + contract: str, + param: str, + storage: str, + expected: str, + big_map_diff: str, + ): + client = client_regtest + contract = path.join(OPCODES_CONTRACT_PATH, contract) + run_script_res = client.run_script( + contract, param, storage, trace_stack=True + ) + assert run_script_res.storage == expected + assert run_script_res.big_map_diff == big_map_diff + + @pytest.mark.parametrize( + "storage,param,expected,big_map_diff", + [ # test swap + ( + '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))', + '(Left Unit)', + '(Left (Pair 0 1))', + [ + ['New map(1) of type (big_map string string)'], + ['Set map(1)["1"] to "one"'], + ['New map(0) of type (big_map string string)'], + ['Set map(0)["2"] to "two"'], + ], + ), + # test reset with new map + ( + '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))', + '(Right (Left (Left (Pair { Elt "3" "three" } ' + + '{ Elt "4" "four" }))))', + '(Left (Pair 0 1))', + [ + ['New map(1) of type (big_map string string)'], + ['Set map(1)["4"] to "four"'], + ['New map(0) of type (big_map string string)'], + ['Set map(0)["3"] to "three"'], + ], + ), + # test reset to unit + ( + '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))', + '(Right (Left (Right Unit)))', + '(Right Unit)', + [], + ), + # test import to big_map + ( + '(Right Unit)', + '(Right (Right (Left (Pair { Pair "foo" "bar" } ' + + '{ Pair "gaz" "baz" }) )))', + '(Left (Pair 0 1))', + [ + ['New map(1) of type (big_map string string)'], + ['Set map(1)["gaz"] to "baz"'], + ['New map(0) of type (big_map string string)'], + ['Set map(0)["foo"] to "bar"'], + ], + ), + # test add to big_map + ( + '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }) )', + '(Right (Right (Right (Left { Pair "3" "three" }))))', + '(Left (Pair 0 1))', + [ + ['New map(1) of type (big_map string string)'], + ['Set map(1)["2"] to "two"'], + ['New map(0) of type (big_map string string)'], + ['Set map(0)["3"] to "three"'], + ['Set map(0)["1"] to "one"'], + ], + ), + # test remove from big_map + ( + '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))', + '(Right (Right (Right (Right { "1" }))))', + '(Left (Pair 0 1))', + [ + ['New map(1) of type (big_map string string)'], + ['Set map(1)["2"] to "two"'], + ['New map(0) of type (big_map string string)'], + ['Unset map(0)["1"]'], + ], + ), + ], + ) + def test_big_map_magic( + self, + client_regtest: ClientRegression, + storage: str, + param: str, + expected: str, + big_map_diff: str, + ): + client = client_regtest + contract = path.join(MINI_SCENARIOS_CONTRACT_PATH, 'big_map_magic.tz') + run_script_res = client.run_script( + contract, storage, param, trace_stack=True + ) + assert run_script_res.storage == expected + assert run_script_res.big_map_diff == big_map_diff + + def test_packunpack(self, client_regtest: ClientRegression): + """Test PACK/UNPACK and binary format.""" + client = client_regtest + assert_run_script_success( + client, + path.join(OPCODES_CONTRACT_PATH, 'packunpack.tz'), + 'Unit', + '(Pair (Pair (Pair "toto" {3;7;9;1}) {1;2;3}) ' + + '0x05070707070100000004746f746f020000000800030' + + '007000900010200000006000100020003)', + ) + assert_run_script_failwith( + client, + path.join(OPCODES_CONTRACT_PATH, 'packunpack.tz'), + 'Unit', + '(Pair (Pair (Pair "toto" {3;7;9;1}) {1;2;3}) ' + + '0x05070707070100000004746f746f020000000800030' + + '0070009000102000000060001000200030004)', + ) + + def test_check_signature(self, client_regtest: ClientRegression): + client = client_regtest + sig = ( + 'edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt' + + '9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF' + ) + assert_run_script_success( + client, + path.join(OPCODES_CONTRACT_PATH, 'check_signature.tz'), + f'(Pair "{sig}" "hello")', + '"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"', + ) + assert_run_script_failwith( + client, + path.join(OPCODES_CONTRACT_PATH, 'check_signature.tz'), + f'(Pair "{sig}" "abcd")', + '"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"', + ) + + def test_hash_consistency_michelson_cli( + self, client_regtest: ClientRegression + ): + client = client_regtest + hash_result = client.hash( + '(Pair 22220000000 (Pair "2017-12-13T04:49:00Z" 034))', + '(pair mutez (pair timestamp int))', + ).blake2b + hash_contract = path.join( + OPCODES_CONTRACT_PATH, 'hash_consistency_checker.tz' + ) + run_script_res = client.run_script( + hash_contract, + '0x00', + '(Pair 22220000000 (Pair "2017-12-13T04:49:00Z" 034))', + ) + assert run_script_res.storage == hash_result + run_script_res = client.run_script( + hash_contract, + '0x00', + '(Pair 22220000000 (Pair "2017-12-13T04:49:00Z" 034))', + ) + assert run_script_res.storage == hash_result + + @pytest.mark.parametrize( + "contract,param,storage", + [ # FORMAT: assert_output contract_file storage input + # Test overflow in shift + ('shifts.tz', 'None', '(Left (Pair 1 257))'), + ('shifts.tz', 'None', '(Left (Pair 123 257))'), + ('shifts.tz', 'None', '(Right (Pair 1 257))'), + ('shifts.tz', 'None', '(Right (Pair 123 257))'), + ('mul_overflow.tz', 'Unit', 'Left Unit'), + ('mul_overflow.tz', 'Unit', 'Right Unit'), + ], + ) + def test_arithmetic_overflow( + self, + client_regtest_scrubbed: ClientRegression, + contract: str, + param: str, + storage: str, + ): + client = client_regtest_scrubbed + contract = path.join(OPCODES_CONTRACT_PATH, contract) + + with assert_run_failure(r'unexpected arithmetic overflow'): + client.run_script(contract, param, storage) + + @pytest.mark.skip(reason="Bug in annotation system") + def test_fails_annotated_set_car_cdr( + self, client_regtest: ClientRegression + ): + """Tests the SET_CAR and SET_CDR instructions.""" + client = client_regtest + + with assert_run_failure(r'The two annotations do not match'): + client.run_script( + path.join(OPCODES_CONTRACT_PATH, 'set_car.tz'), + '(Pair %wrong %field "hello" 0)', + '""', + ) + + @pytest.mark.parametrize( + "contract,storage,param,expected", + [ # FORMAT: assert_output contract_file storage input expected_result + # Mapping over maps + ('map_map_sideeffect.tz', '(Pair {} 0)', '10', '(Pair {} 0)'), + ( + 'map_map_sideeffect.tz', + '(Pair { Elt "foo" 1 } 1)', + '10', + '(Pair { Elt "foo" 11 } 11)', + ), + ( + 'map_map_sideeffect.tz', + '(Pair { Elt "bar" 5 ; Elt "foo" 1 } 6)', + '15', + '(Pair { Elt "bar" 20 ; Elt "foo" 16 } 36)', + ), + ], + ) + def test_map_map_sideeffect( + self, + client_regtest: ClientRegression, + contract: str, + param: str, + storage: str, + expected: str, + ): + client = client_regtest + contract = path.join(OPCODES_CONTRACT_PATH, contract) + run_script_res = client.run_script(contract, storage, param) + assert run_script_res.storage == expected diff --git a/tests_python/tests_009/test_cors.py b/tests_python/tests_009/test_cors.py new file mode 100644 index 0000000000000000000000000000000000000000..80b064285d86d14645e724f53cdf955c85b85b0d --- /dev/null +++ b/tests_python/tests_009/test_cors.py @@ -0,0 +1,47 @@ +import pytest +from daemons.node import Node +from launchers.sandbox import Sandbox +from tools import utils + + +@pytest.fixture(scope="class") +def node(sandbox: Sandbox): + """Launches one node in sandbox mode (genesis)""" + sandbox.add_node(0, params=['--cors-origin', '*']) + yield sandbox.node(0) + + +class TestCors: + def test_preflight(self, node: Node): + origin = 'localhost' + port = node.rpc_port + headers = { + 'Origin': origin, + 'Access-Control-Request-Method': 'GET', + 'Access-Control-Request-Headers': 'Content-Type', + } + res = utils.rpc( + origin, + port, + 'options', + '/chains/main/blocks/head/header/shell', + headers=headers, + ) + print(res.headers) + assert res.headers["access-control-allow-origin"] == '*' + assert res.headers["access-control-allow-methods"] == 'GET' + assert res.headers["access-control-allow-headers"] == 'Content-Type' + + def test_request(self, node: Node): + origin = 'localhost' + port = node.rpc_port + headers = {'Origin': origin, 'Content-Type': 'application/json'} + res = utils.rpc( + origin, + port, + 'get', + '/chains/main/blocks/head/header/shell', + headers=headers, + ) + print(res.headers) + assert res.headers["access-control-allow-origin"] == '*' diff --git a/tests_python/tests_009/test_crypto.py b/tests_python/tests_009/test_crypto.py new file mode 100644 index 0000000000000000000000000000000000000000..995b48fdf617a98b1b921b13f8ff876b2bbde349 --- /dev/null +++ b/tests_python/tests_009/test_crypto.py @@ -0,0 +1,47 @@ +from random import getrandbits + +from os import path + +import pytest + +from Crypto.Hash import keccak, SHA3_256 + +from .contract_paths import OPCODES_CONTRACT_PATH + +RANDOM_ITERATIONS = 50 + +HASH_FUNCTIONS = { + "keccak": lambda bytes_to_hash: keccak.new(digest_bits=256) + .update(bytes_to_hash) + .hexdigest(), + "sha3": lambda bytes_to_hash: SHA3_256.new() + .update(bytes_to_hash) + .hexdigest(), +} + + +@pytest.fixture(params=HASH_FUNCTIONS.keys()) +def hash_fun(request): + return request.param + + +@pytest.mark.contract +class TestHash: + @pytest.mark.parametrize( + "bytes_to_hash", + [b"", b"a"] + + [ + getrandbits(bytes_length * 8).to_bytes( + bytes_length, byteorder="little" + ) + for bytes_length in [32] + for _ in range(RANDOM_ITERATIONS) + ], + ) + def test_hash(self, client, hash_fun, bytes_to_hash): + contract = path.join(OPCODES_CONTRACT_PATH, f"{hash_fun}.tz") + + hashed = HASH_FUNCTIONS[hash_fun](bytes_to_hash) + arg = f"0x{bytes_to_hash.hex()}" + result = client.run_script(contract, "None", arg) + assert result.storage == f"(Some 0x{hashed})" diff --git a/tests_python/tests_009/test_deprecated_rpc.py b/tests_python/tests_009/test_deprecated_rpc.py new file mode 100644 index 0000000000000000000000000000000000000000..722acda71b6a615489ac4e664a87e6f039eb7b8b --- /dev/null +++ b/tests_python/tests_009/test_deprecated_rpc.py @@ -0,0 +1,152 @@ +import json +import os +import datetime + +import pytest + +from tools import constants, paths + +# This test check that the deprecated RPC in protocol alpha works as in delphi. +# This test can be removed after the activation of the protocol 008 that will +# contains the deprecated RPC or after the removal of the deprecated RPC in a +# futur protocol. To do that it runs the same test twice, first with delphi +# activated then with alpha activated. + +BAKER = 'bootstrap1' +BAKE_ARGS = [ + '--minimal-fees', + '0', + '--minimal-nanotez-per-byte', + '0', + '--minimal-nanotez-per-gas-unit', + '0', + '--max-priority', + '512', + '--minimal-timestamp', +] +PROTO_A = constants.DELPHI +PROTO_A_DAEMON = constants.DELPHI_DAEMON +PROTO_A_PATH = f"proto_{PROTO_A_DAEMON.replace('-','_')}" + +PROTO_A_PARAMETERS_FILE = ( + f'{paths.TEZOS_HOME}src/{PROTO_A_PATH}/parameters/' + 'sandbox-parameters.json' +) +assert os.path.isfile(PROTO_A_PARAMETERS_FILE), ( + f'{PROTO_A_PARAMETERS_FILE}' + ' cannot be found; please ' + 'first run `make` in ' + '{paths.TEZOS_HOME}.' +) +with open(PROTO_A_PARAMETERS_FILE) as f: + PROTO_A_PARAMETERS = dict(json.load(f)) + +PROTO_B = constants.ALPHA +PROTO_B_PARAMETERS = constants.ALPHA_PARAMETERS + +BLOCKS_PER_CYCLE = 4 +CYCLE_PER_VOTING_PERIOD = 5 +BLOCKS_PER_VOTING_PERIOD = BLOCKS_PER_CYCLE * CYCLE_PER_VOTING_PERIOD + + +@pytest.fixture(scope="class") +def client(sandbox, protocol, parameters, node_id): + # Scenarios run one after the other. To be able to create a new node with a + # different protocol on the second scenario we need to delete the previous + # node before. + for i in range(node_id): + sandbox.rm_node(i) + sandbox.add_node(node_id, params=constants.NODE_PARAMS) + parameters["blocks_per_cycle"] = BLOCKS_PER_CYCLE + parameters["blocks_per_voting_period"] = BLOCKS_PER_VOTING_PERIOD + delay = datetime.timedelta(seconds=3600 * 24 * 365) + sandbox.client(node_id).activate_protocol_json( + protocol, parameters, delay=delay + ) + yield sandbox.client(node_id) + + +def pytest_generate_tests(metafunc): + # this function annotates correctly all test with the value from the + # declared scenario. + idlist = [] + argvalues = [] + for scenario in metafunc.cls.scenarios: + idlist.append(scenario[0]) + items = scenario[1].items() + argnames = [x[0] for x in items] + argvalues.append([x[1] for x in items]) + metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class") + + +SCENARIO_PROTO_A = ( + PROTO_A, + {"node_id": 0, "protocol": PROTO_A, "parameters": PROTO_A_PARAMETERS}, +) +SCENARIO_PROTO_B = ( + PROTO_B, + {"node_id": 1, "protocol": PROTO_B, "parameters": PROTO_B_PARAMETERS}, +) + + +@pytest.mark.incremental +class TestRpc: + scenarios = [SCENARIO_PROTO_A, SCENARIO_PROTO_B] + + def test_activate(self, client, protocol): + client.bake(BAKER, BAKE_ARGS) + assert client.get_protocol() == protocol + + def test_rpc(self, client): + current_period_kind = client.get_current_period_kind() + current_level = client.get_current_level() + metadata = client.get_metadata() + meta_level = metadata["level"] + meta_period_kind = metadata["voting_period_kind"] + assert current_period_kind == meta_period_kind + assert current_level == meta_level + assert current_level["level"] == 2 + assert current_level["level_position"] == 1 + assert current_level["cycle"] == 0 + assert current_level["cycle_position"] == 1 + assert current_level["voting_period"] == 0 + assert current_level["voting_period_position"] == 1 + assert current_period_kind == "proposal" + + def test_bake_last_block(self, client): + for _i in range(BLOCKS_PER_VOTING_PERIOD - 2): + client.bake(BAKER, BAKE_ARGS) + + def test_rpc_test_last_block(self, client): + current_period_kind = client.get_current_period_kind() + current_level = client.get_current_level() + metadata = client.get_metadata() + meta_level = metadata["level"] + meta_period_kind = metadata["voting_period_kind"] + assert current_period_kind == meta_period_kind + assert current_level == meta_level + assert current_level["level"] == BLOCKS_PER_VOTING_PERIOD + assert current_level["level_position"] == BLOCKS_PER_VOTING_PERIOD - 1 + assert current_level["cycle"] == CYCLE_PER_VOTING_PERIOD - 1 + assert current_level["cycle_position"] == BLOCKS_PER_CYCLE - 1 + assert current_level["voting_period"] == 0 + current_lvl_voting_position = current_level["voting_period_position"] + assert current_lvl_voting_position == BLOCKS_PER_VOTING_PERIOD - 1 + assert current_period_kind == "proposal" + + def test_rpc_next_period(self, client): + client.bake(BAKER, BAKE_ARGS) + current_period_kind = client.get_current_period_kind() + current_level = client.get_current_level() + metadata = client.get_metadata() + meta_level = metadata["level"] + meta_period_kind = metadata["voting_period_kind"] + assert current_period_kind == meta_period_kind + assert current_level == meta_level + assert current_level["level"] == BLOCKS_PER_VOTING_PERIOD + 1 + assert current_level["level_position"] == BLOCKS_PER_VOTING_PERIOD + assert current_level["cycle"] == CYCLE_PER_VOTING_PERIOD + assert current_level["cycle_position"] == 0 + assert current_level["voting_period"] == 1 + assert current_level["voting_period_position"] == 0 + assert current_period_kind == "proposal" diff --git a/tests_python/tests_009/test_double_endorsement.py b/tests_python/tests_009/test_double_endorsement.py new file mode 100644 index 0000000000000000000000000000000000000000..5ff2c4943c3d4df0e6619bef9c2f9260d46f39b3 --- /dev/null +++ b/tests_python/tests_009/test_double_endorsement.py @@ -0,0 +1,119 @@ +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox +from . import protocol + + +BAKE_ARGS = ['--max-priority', '512', '--minimal-timestamp'] +NUM_NODES = 3 + + +@pytest.mark.multinode +@pytest.mark.incremental +class TestDoubleEndorsement: + """Constructs a double endorsement, and build evidence.""" + + def test_init(self, sandbox: Sandbox): + for i in range(NUM_NODES): + sandbox.add_node(i, params=constants.NODE_PARAMS) + protocol.activate(sandbox.client(0), activate_in_the_past=True) + sandbox.client(0).bake('bootstrap1', BAKE_ARGS) + + def test_level(self, sandbox: Sandbox): + level = 2 + for client in sandbox.all_clients(): + assert utils.check_level(client, level) + + def test_terminate_nodes_1_and_2(self, sandbox: Sandbox): + sandbox.node(1).terminate() + sandbox.node(2).terminate() + + def test_bake_node_0(self, sandbox: Sandbox): + """Client 0 bakes block A at level 3, not communicated to 1 and 2 + Inject an endorsement to ensure a different hash""" + sandbox.client(0).endorse('bootstrap1') + sandbox.client(0).bake('bootstrap1', BAKE_ARGS) + + def test_endorse_node_0(self, sandbox: Sandbox, session: dict): + """bootstrap1 builds an endorsement for block A""" + client = sandbox.client(0) + client.endorse('bootstrap1') + mempool = client.get_mempool() + endorsement = mempool['applied'][0] + session['endorsement1'] = endorsement + + def test_terminate_node_0(self, sandbox: Sandbox): + sandbox.node(0).terminate() + + def test_restart_node_2(self, sandbox: Sandbox): + sandbox.node(2).run() + assert sandbox.client(2).check_node_listening() + + def test_bake_node_2(self, sandbox: Sandbox): + """Client 2 bakes block B at level 3, not communicated to 0 and 1""" + sandbox.client(2).bake('bootstrap1', BAKE_ARGS) + + def test_endorse_node_2(self, sandbox: Sandbox, session: dict): + """bootstrap1 builds an endorsement for block B""" + client = sandbox.client(2) + client.endorse('bootstrap1') + mempool = client.get_mempool() + endorsement = mempool['applied'][0] + session['endorsement2'] = endorsement + sandbox.client(2).endorse('bootstrap2') + + def test_restart_all(self, sandbox: Sandbox): + sandbox.node(0).run() + sandbox.node(1).run() + sandbox.client(0).check_node_listening() + sandbox.client(1).check_node_listening() + + def test_check_level(self, sandbox: Sandbox): + """All nodes are at level 3, head is either block A or B""" + level = 3 + for client in sandbox.all_clients(): + assert utils.check_level(client, level) + + def test_forge_accusation(self, sandbox: Sandbox, session: dict): + """Forge and inject a double endorsement evidence operation""" + client = sandbox.client(1) + head_hash = client.get_head()['hash'] + + # Extract the `Endorsement` ops and the slot out of the + # `Endorsement_with_slot` ops + endorsement1 = session['endorsement1']['contents'][0]['endorsement'] + endorsement2 = session['endorsement2']['contents'][0]['endorsement'] + slot = session['endorsement1']['contents'][0]['slot'] + + operation = { + 'branch': head_hash, + 'contents': [ + { + 'kind': 'double_endorsement_evidence', + 'op1': endorsement1, + 'op2': endorsement2, + 'slot': slot, + } + ], + } + + path_forge_operation = ( + '/chains/main/blocks/head/helpers/forge/operations' + ) + operation_hex_string = client.rpc( + 'post', path_forge_operation, data=operation + ) + assert isinstance(operation_hex_string, str) + sender_sk_long = constants.IDENTITIES['bootstrap1']['secret'] + sender_sk = sender_sk_long[len('unencrypted:') :] + signed_op = utils.sign_operation(operation_hex_string, sender_sk) + op_hash = client.rpc('post', 'injection/operation', signed_op) + assert isinstance(op_hash, str) + session['operation'] = op_hash + + def test_operation_applied(self, sandbox: Sandbox, session: dict): + """Check operation is in mempool""" + client = sandbox.client(1) + assert utils.check_mempool_contains_operations( + client, [session['operation']] + ) diff --git a/tests_python/tests_009/test_forge_block.py b/tests_python/tests_009/test_forge_block.py new file mode 100755 index 0000000000000000000000000000000000000000..1aa64a36b47795418ce77dc446283378ebad2018 --- /dev/null +++ b/tests_python/tests_009/test_forge_block.py @@ -0,0 +1,47 @@ +import datetime +import pytest +from tools import constants +from launchers.sandbox import Sandbox + +PROTO_DEMO = 'ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp' + + +@pytest.mark.slow +@pytest.mark.incremental +class TestForgeBlock: + """ Check that a block more than 15 seconds in the future is rejected """ + + def test_setup_network(self, sandbox: Sandbox): + sandbox.add_node(1, params=constants.NODE_PARAMS) + + def test_protocol_exists(self, sandbox: Sandbox): + client = sandbox.client(1) + protocols = client.list_protocols() + assert PROTO_DEMO in protocols + + def test_activate_proto_demo_time_shifted_ok(self, sandbox: Sandbox): + parameters = {} # type: dict + delta = datetime.timedelta(seconds=10) + sandbox.client(1).activate_protocol_json( + PROTO_DEMO, + parameters, + key='activator', + timestamp=(datetime.datetime.utcnow() + delta).strftime( + "%Y-%m-%dT%H:%M:%SZ" + ), + fitness='1', + ) + + @pytest.mark.xfail + def test_activate_proto_demo_time_shifted_ko(self, sandbox: Sandbox): + parameters = {} # type: dict + delta = datetime.timedelta(seconds=30) + sandbox.client(1).activate_protocol_json( + PROTO_DEMO, + parameters, + key='activator', + timestamp=(datetime.datetime.utcnow() + delta).strftime( + "%Y-%m-%dT%H:%M:%SZ" + ), + fitness='1', + ) diff --git a/tests_python/tests_009/test_fork.py b/tests_python/tests_009/test_fork.py new file mode 100644 index 0000000000000000000000000000000000000000..6cbeffde13b37779a2ccd55f54d5fe0752db7a7f --- /dev/null +++ b/tests_python/tests_009/test_fork.py @@ -0,0 +1,86 @@ +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox +from . import protocol + + +BAKE_ARGS = ['--max-priority', '512', '--minimal-timestamp'] +NUM_NODES = 3 + + +@pytest.mark.multinode +@pytest.mark.incremental +class TestFork: + """Constructs two independent branches on disconnected subsets of nodes, + one head has higher fitness. At reconnection, check the the highest + fitness head is the chosen one""" + + def test_init(self, sandbox: Sandbox): + for i in range(NUM_NODES): + sandbox.add_node(i, params=constants.NODE_PARAMS) + protocol.activate(sandbox.client(0)) + + def test_level(self, sandbox: Sandbox): + level = 1 + for client in sandbox.all_clients(): + assert utils.check_level(client, level) + + def test_terminate_nodes_1_and_2(self, sandbox: Sandbox): + sandbox.node(1).terminate() + sandbox.node(2).terminate() + + def test_bake_node_0(self, sandbox: Sandbox): + """Client 0 bakes block A at level 2, not communicated to 1 and 2""" + sandbox.client(0).bake('bootstrap1', BAKE_ARGS) + + def test_endorse_node_0(self, sandbox: Sandbox, session: dict): + """bootstrap1 builds an endorsement for block A""" + client = sandbox.client(0) + client.endorse('bootstrap1') + mempool = client.get_mempool() + endorsement = mempool['applied'][0] + session['endorsement1'] = endorsement + + def test_bake_node_0_again(self, sandbox: Sandbox): + """Client 0 bakes block A' at level 3, not communicated to 1 and 2""" + sandbox.client(0).bake('bootstrap1', BAKE_ARGS) + + def test_first_branch(self, sandbox: Sandbox, session: dict): + head = sandbox.client(0).get_head() + assert head['header']['level'] == 3 + session['hash1'] = head['hash'] + assert len(head['operations'][0]) == 1 + + def test_terminate_node_0(self, sandbox: Sandbox): + sandbox.node(0).terminate() + + def test_restart_node_2(self, sandbox: Sandbox): + sandbox.node(2).run() + assert sandbox.client(2).check_node_listening() + + def test_bake_node_2(self, sandbox: Sandbox): + """Client 2 bakes block B at level 2, not communicated to 0 and 1""" + sandbox.client(2).bake('bootstrap1', BAKE_ARGS) + + def test_bake_node_2_again(self, sandbox: Sandbox): + """Client 2 bakes block B' at level 3, not communicated to 0 and 1""" + sandbox.client(2).bake('bootstrap1', BAKE_ARGS) + + def test_second_branch(self, sandbox: Sandbox, session: dict): + head = sandbox.client(2).get_head() + session['hash2'] = head['hash'] + assert head['header']['level'] == 3 + assert not head['operations'][0] + + def test_restart_all(self, sandbox: Sandbox): + sandbox.node(0).run() + sandbox.node(1).run() + assert sandbox.client(0).check_node_listening() + assert sandbox.client(1).check_node_listening() + + +# def test_check_head(self, sandbox: Sandbox, session: dict): +# """All nodes are at level 3, head should be hash1""" +# for client in sandbox.all_clients(): +# head = client.get_head() +# assert session['hash1'] == head['hash'] diff --git a/tests_python/tests_009/test_injection.py b/tests_python/tests_009/test_injection.py new file mode 100644 index 0000000000000000000000000000000000000000..c5b5c06b5b533c1090c04aa522d58d9d97831da5 --- /dev/null +++ b/tests_python/tests_009/test_injection.py @@ -0,0 +1,102 @@ +import os +from typing import List +import subprocess +import pytest +from tools import utils, paths, constants +from client.client import Client + + +@pytest.fixture(scope="class") +def clients(sandbox): + """Launches 3 nodes in sandbox mode (genesis, doesn't activate alpha).""" + num_nodes = 3 + for i in range(num_nodes): + sandbox.add_node(i, params=constants.NODE_PARAMS) + yield sandbox.all_clients() + + +PROTO = f'{paths.TEZOS_HOME}/src/bin_client/test/proto_test_injection' +COMPILER = ( + f'{paths.TEZOS_HOME}/_build/default/src/lib_protocol_compiler/' + 'main_native.exe' +) +PARAMS = ['-p', 'ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im'] + + +@pytest.mark.incremental +class TestInjectionAndActivation: + """Protocol injection and activation""" + + def test_check_resources(self): + assert os.path.isfile(COMPILER) + assert os.path.isdir(PROTO) + + def test_compute_hash(self, session: dict): + cmd = [COMPILER, '-hash-only', PROTO] + res = subprocess.run( + cmd, universal_newlines=True, check=True, stdout=subprocess.PIPE + ) + proto_hash = res.stdout[:-1] + assert len(proto_hash) == 51 + session['proto_hash'] = proto_hash + + def test_injection(self, clients: List[Client]): + clients[0].inject_protocol(PROTO) + + def test_check_injected(self, clients: List[Client], session: dict): + proto = session['proto_hash'] + protos = clients[0].list_protocols() + assert proto in protos + + def test_environment_version(self, clients: List[Client], session: dict): + proto = session['proto_hash'] + assert clients[0].environment_protocol(proto) == "V1" + + def test_activation(self, clients: List[Client], session: dict): + proto = session['proto_hash'] + parameters = {} # type: dict + res = clients[0].activate_protocol_json( + proto, parameters, key='activator', fitness='1' + ) + assert res.block_hash + + def test_check_protocol(self, clients: List[Client], session: dict): + proto = session['proto_hash'] + for client in clients: + assert utils.check_protocol(client, proto, params=PARAMS) + + +@pytest.fixture(scope="class") +def client(sandbox): + """One node in sandbox mode (genesis, doesn't activate alpha).""" + sandbox.add_node(0) + client = sandbox.client(0) + yield client + + +@pytest.mark.incremental +class TestActivation: + """ Protocol activation (protocol already linked to the node) """ + + def test_proto_known(self, client: Client): + res = client.list_protocols() + assert 'ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp' in res + + def test_first_protocol(self, client: Client): + proto = 'PrihK96nBAFSxVL1GLJTVhu9YnzkMFiBeuJRPA8NwuZVZCE1L6i' + assert client.get_protocol() == proto + + def test_activate_demo(self, client: Client): + proto = 'ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp' + parameters = {} # type: dict + res = client.activate_protocol_json( + proto, parameters, key='activator', fitness='1' + ) + assert res.block_hash + + def test_level1(self, client: Client): + assert client.get_level(params=PARAMS) == 1 + + def test_protocol_genesis(self, client: Client): + proto = 'ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im' + assert client.get_protocol(params=PARAMS) == proto diff --git a/tests_python/tests_009/test_many_bakers.py b/tests_python/tests_009/test_many_bakers.py new file mode 100644 index 0000000000000000000000000000000000000000..8038c6cf8067aeaa6f4ddcdcf3af1fcd0e16d725 --- /dev/null +++ b/tests_python/tests_009/test_many_bakers.py @@ -0,0 +1,40 @@ +import time +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox +from . import protocol + + +# TODO parameterize test + + +@pytest.mark.baker +@pytest.mark.multinode +@pytest.mark.slow +@pytest.mark.incremental +class TestManyBakers: + """Run 5 bakers and num nodes, wait and check logs""" + + def test_init(self, sandbox: Sandbox): + for i in range(10): + sandbox.add_node(i, params=constants.NODE_PARAMS) + protocol.activate(sandbox.client(0)) + for i in range(5): + sandbox.add_baker(i, f'bootstrap{i + 1}', proto=protocol.DAEMON) + + def test_wait(self): + time.sleep(10) + + def test_progress(self, sandbox: Sandbox): + min_level = min( + [client.get_level() for client in sandbox.all_clients()] + ) + assert min_level >= 3 + + @pytest.mark.xfail + def test_check_logs(self, sandbox: Sandbox): + if not sandbox.log_dir: + pytest.skip() + assert sandbox.logs + error_pattern = r"canceled|crashed" + assert utils.check_logs(sandbox.logs, error_pattern) diff --git a/tests_python/tests_009/test_many_nodes.py b/tests_python/tests_009/test_many_nodes.py new file mode 100644 index 0000000000000000000000000000000000000000..816350aa12566b0517415c33aba3bba85f03256e --- /dev/null +++ b/tests_python/tests_009/test_many_nodes.py @@ -0,0 +1,63 @@ +import random +import time +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox +from . import protocol + +NUM_NODES = 2 +NEW_NODES = 2 +REPLACE = False +ERROR_PATTERN = r"Uncaught|registered" + + +@pytest.mark.baker +@pytest.mark.multinode +@pytest.mark.slow +@pytest.mark.incremental +class TestManyNodesBootstrap: + """Run many nodes, wait a while, run more nodes, check logs""" + + def test_init(self, sandbox: Sandbox): + sandbox.add_node(0, params=constants.NODE_PARAMS) + parameters = dict(protocol.PARAMETERS) + parameters["time_between_blocks"] = ["1", "0"] + protocol.activate(sandbox.client(0), parameters) + sandbox.add_baker(0, 'bootstrap1', proto=protocol.DAEMON) + sandbox.add_node(1, params=constants.NODE_PARAMS) + sandbox.add_baker(1, 'bootstrap2', proto=protocol.DAEMON) + + def test_add_nodes(self, sandbox: Sandbox): + for i in range(2, NUM_NODES): + sandbox.add_node(i, params=constants.NODE_PARAMS) + + def test_sleep_10s(self): + time.sleep(10) + + def test_add_more_nodes(self, sandbox: Sandbox): + new_node = NUM_NODES + for i in range(NEW_NODES): + if REPLACE: + running_nodes = list(sandbox.nodes.keys()) + running_nodes.remove(0) + running_nodes.remove(1) + sandbox.rm_node(random.choice(running_nodes)) + sandbox.add_node(new_node + i, params=constants.NODE_PARAMS) + + def test_kill_baker(self, sandbox: Sandbox): + assert utils.check_logs(sandbox.logs, ERROR_PATTERN) + sandbox.rm_baker(0, proto=protocol.DAEMON) + sandbox.rm_baker(1, proto=protocol.DAEMON) + + def test_synchronize(self, sandbox: Sandbox): + utils.synchronize(sandbox.all_clients()) + + def test_progress(self, sandbox: Sandbox): + level = sandbox.client(0).get_level() + assert level >= 5 + + def test_check_logs(self, sandbox: Sandbox): + if not sandbox.log_dir: + pytest.skip() + assert sandbox.logs + assert utils.check_logs(sandbox.logs, ERROR_PATTERN) diff --git a/tests_python/tests_009/test_mempool.py b/tests_python/tests_009/test_mempool.py new file mode 100644 index 0000000000000000000000000000000000000000..404e03ba8ac161c2af83e428c178c0e69f766f3d --- /dev/null +++ b/tests_python/tests_009/test_mempool.py @@ -0,0 +1,68 @@ +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox + +from . import protocol + +BAKE_ARGS = ['--max-priority', '512', '--minimal-timestamp'] + + +@pytest.mark.mempool +@pytest.mark.multinode +@pytest.mark.slow +@pytest.mark.incremental +class TestMempool: + " Tests mempool" + + def test_init(self, sandbox: Sandbox): + sandbox.add_node(1, params=constants.NODE_PARAMS) + sandbox.add_node(2, params=constants.NODE_PARAMS) + sandbox.add_node( + 3, params=constants.NODE_PARAMS + ['--disable-mempool'] + ) + protocol.activate(sandbox.client(1), activate_in_the_past=True) + + def test_level1(self, sandbox: Sandbox): + level = 1 + for client in sandbox.all_clients(): + assert utils.check_level(client, level) + + def test_running_prevalidators(self, sandbox: Sandbox): + assert sandbox.client(1).get_prevalidator() + assert sandbox.client(2).get_prevalidator() + assert not sandbox.client(3).get_prevalidator() + + def test_mempool_empty(self, sandbox: Sandbox): + for i in range(1, 4): + assert sandbox.client(i).mempool_is_empty() + + def test_transfer(self, sandbox: Sandbox, session: dict): + client = sandbox.client(1) + session['trsfr_hash'] = client.transfer( + 1.000, 'bootstrap1', 'bootstrap2' + ).operation_hash + + def test_mempool_include_transfer(self, sandbox: Sandbox, session: dict): + assert utils.check_mempool_contains_operations( + sandbox.client(1), [session['trsfr_hash']] + ) + assert utils.check_mempool_contains_operations( + sandbox.client(2), [session['trsfr_hash']] + ) + assert sandbox.client(3).mempool_is_empty() + + def test_bake_for1(self, sandbox: Sandbox): + sandbox.client(1).bake('bootstrap1', BAKE_ARGS) + + def test_level2(self, sandbox: Sandbox): + level = 2 + for client in sandbox.all_clients(): + assert utils.check_level(client, level) + + def test_mempools_are_empty(self, sandbox: Sandbox): + for i in range(1, 4): + assert sandbox.client(i).mempool_is_empty() + + def test_injection_fails_on_mempool_disabled_node(self, sandbox: Sandbox): + with pytest.raises(Exception): + sandbox.client(3).transfer(2.000, 'bootstrap2', 'bootstrap3') diff --git a/tests_python/tests_009/test_migration.py b/tests_python/tests_009/test_migration.py new file mode 100644 index 0000000000000000000000000000000000000000..a22b28cc548bcf9d59a952e5a3c4b11f2f831472 --- /dev/null +++ b/tests_python/tests_009/test_migration.py @@ -0,0 +1,216 @@ +import datetime +import json +import os +import time +from typing import List + +import pytest + +from launchers.sandbox import Sandbox +from tools import constants, paths, utils + +BAKE_ARGS = [ + '--minimal-fees', + '0', + '--minimal-nanotez-per-byte', + '0', + '--minimal-nanotez-per-gas-unit', + '0', + '--max-priority', + '512', + '--minimal-timestamp', +] +PROTO_A = constants.EDO +PROTO_A_DAEMON = constants.EDO_DAEMON +PROTO_A_PATH = f"proto_{PROTO_A_DAEMON.replace('-','_')}" +PROTO_B = constants.ALPHA + +PARAMETERS_FILE = ( + f'{paths.TEZOS_HOME}src/{PROTO_A_PATH}/parameters/' 'test-parameters.json' +) +assert os.path.isfile(PARAMETERS_FILE), ( + f'{PARAMETERS_FILE}' + ' cannot be found; please first run' + ' `make` in {paths.TEZOS_HOME}.' +) +with open(PARAMETERS_FILE) as f: + PARAMETERS = dict(json.load(f)) +MIGRATION_LEVEL = 3 +BAKER = 'bootstrap1' + +BAKER_PKH = constants.IDENTITIES[BAKER]['identity'] +DEPOSIT_RECEIPTS = [ + {"kind": "contract", "contract": BAKER_PKH, "change": "-512000000"}, + { + "kind": "freezer", + "category": "deposits", + "delegate": BAKER_PKH, + "cycle": 0, + "change": "512000000", + }, +] +# in Alpha protocol, the "origin" field is added +ALPHA_DEPOSIT_RECEIPTS = [ + { + "kind": "contract", + "contract": BAKER_PKH, + "change": "-512000000", + "origin": "block", + }, + { + "kind": "freezer", + "category": "deposits", + "delegate": BAKER_PKH, + "cycle": 0, + "change": "512000000", + "origin": "block", + }, +] +MIGRATION_RECEIPTS: List[object] = [ + { + "kind": "contract", + "contract": 'tz1abmz7jiCV2GH2u81LRrGgAFFgvQgiDiaf', + "change": "100000000", + "origin": "migration", + }, +] + +# configure user-activate-upgrade at MIGRATION_LEVEL to test migration +NODE_CONFIG = { + 'network': { + 'genesis': { + 'timestamp': '2018-06-30T16:07:32Z', + 'block': 'BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2', + 'protocol': 'ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im', + }, + 'genesis_parameters': { + 'values': {'genesis_pubkey': constants.GENESIS_PK} + }, + 'chain_name': 'TEZOS', + 'sandboxed_chain_name': 'SANDBOXED_TEZOS', + 'user_activated_upgrades': [ + {'level': MIGRATION_LEVEL, 'replacement_protocol': PROTO_B} + ], + } +} + + +@pytest.fixture(scope="class") +def client(sandbox): + sandbox.add_node(0, node_config=NODE_CONFIG) + delay = datetime.timedelta(seconds=3600 * 24 * 365) + sandbox.client(0).activate_protocol_json(PROTO_A, PARAMETERS, delay=delay) + + yield sandbox.client(0) + + +@pytest.mark.incremental +class TestMigration: + """Test migration from PROTO_A to PROTO_B.""" + + def test_init(self, client): + # 1: genesis block + client.get_head() + client.rpc('get', '/config/network/user_activated_upgrades') + + def test_activate(self, client, sandbox): + # 2: activated PROTO_A + client.bake(BAKER, BAKE_ARGS) + assert client.get_protocol() == PROTO_A + assert sandbox.client(0).get_head()['header']['proto'] == 1 + metadata = client.get_metadata() + assert metadata['balance_updates'] == DEPOSIT_RECEIPTS + # PROTO_A is using env. V1, metadata hashes should be present + _ops_metadata_hash = client.get_operations_metadata_hash() + _block_metadata_hash = client.get_block_metadata_hash() + + def test_migration(self, client, sandbox): + # 3: last block of PROTO_A, runs migration code (MIGRATION_LEVEL) + client.bake(BAKER, BAKE_ARGS) + metadata = client.get_metadata() + assert metadata['next_protocol'] == PROTO_B + assert metadata['balance_updates'] == DEPOSIT_RECEIPTS + # PROTO_B is using env. V1, metadata hashes should be present + _ops_metadata_hash = client.get_operations_metadata_hash() + _block_metadata_hash = client.get_block_metadata_hash() + assert sandbox.client(0).get_head()['header']['proto'] == 2 + + def test_new_proto(self, client, sandbox): + # 4: first block of PROTO_B + client.bake(BAKER, BAKE_ARGS) + assert client.get_protocol() == PROTO_B + assert sandbox.client(0).get_head()['header']['proto'] == 2 + + # check that migration balance update appears in receipts + metadata = client.get_metadata() + assert metadata['balance_updates'] == ( + MIGRATION_RECEIPTS + ALPHA_DEPOSIT_RECEIPTS + ) + _ops_metadata_hash = client.get_operations_metadata_hash() + _block_metadata_hash = client.get_block_metadata_hash() + + def test_new_proto_second(self, client): + # 5: second block of PROTO_B + client.bake(BAKER, BAKE_ARGS) + metadata = client.get_metadata() + assert metadata['balance_updates'] == ALPHA_DEPOSIT_RECEIPTS + + def test_terminate_node0(self, client, sandbox: Sandbox, session: dict): + # # to export rolling snapshot, we need to be at level > 60 + # (see `max_operations_ttl`) + level = client.get_head()['header']['level'] + for _ in range(60 - level + 1): + client.bake(BAKER, BAKE_ARGS) + assert client.get_head()['header']['level'] == 61 + + # terminate node0 + session['head_hash'] = sandbox.client(0).get_head()['hash'] + sandbox.node(0).terminate() + time.sleep(1) + + def test_export_snapshots(self, sandbox, tmpdir, session: dict): + node_export = sandbox.node(0) + file_full = f'{tmpdir}/FILE.full' + file_rolling = f'{tmpdir}/FILE.rolling' + head_hash = session['head_hash'] + session['snapshot_full'] = file_full + session['snapshot_rolling'] = file_rolling + node_export.snapshot_export(file_full, params=['--block', head_hash]) + node_export.snapshot_export( + file_rolling, params=['--block', head_hash, '--rolling'] + ) + + def test_import_full_snapshot_node1(self, sandbox, session): + sandbox.add_node( + 1, snapshot=session['snapshot_full'], node_config=NODE_CONFIG + ) + client = sandbox.client(1) + client.bake(BAKER, BAKE_ARGS) + + def test_import_rolling_snapshot_node2(self, sandbox, session): + sandbox.add_node( + 2, snapshot=session['snapshot_rolling'], node_config=NODE_CONFIG + ) + client = sandbox.client(2) + utils.synchronize([sandbox.client(1), client], max_diff=0) + client.bake(BAKER, BAKE_ARGS) + + def test_reconstruct_full_node3(self, sandbox, session): + sandbox.add_node( + 3, snapshot=session['snapshot_full'], node_config=NODE_CONFIG + ) + sandbox.node(3).terminate() + time.sleep(3) + sandbox.node(3).reconstruct() + sandbox.node(3).run() + client = sandbox.client(3) + assert client.check_node_listening() + utils.synchronize( + [sandbox.client(1), sandbox.client(2), client], max_diff=0 + ) + client.bake(BAKER, BAKE_ARGS) + + def test_rerun_node0(self, sandbox): + sandbox.node(0).run() + sandbox.client(0).check_node_listening() + utils.synchronize(sandbox.all_clients(), max_diff=0) diff --git a/tests_python/tests_009/test_mockup.py b/tests_python/tests_009/test_mockup.py new file mode 100644 index 0000000000000000000000000000000000000000..67b485c237a126baf696567d55473cfb2367c4e1 --- /dev/null +++ b/tests_python/tests_009/test_mockup.py @@ -0,0 +1,689 @@ +""" This file tests the mockup mode (tezos-client --mode mockup). + In this mode the client does not need a node running. + + Make sure to either use the fixture mockup_client or + to mimick it if you want a mockup with custom parameters. + + Care is taken not to leave any base_dir dangling after + tests are finished. Please continue doing this. +""" +import json +import os +import re +import shutil +import tempfile +from pathlib import Path +from typing import Any, List, Optional, Tuple +import pytest +from launchers.sandbox import Sandbox +from client.client import Client +from client.client_output import CreateMockupResult + +from . import protocol + +_BA_FLAG = "bootstrap-accounts" +_PC_FLAG = "protocol-constants" + + +@pytest.mark.client +def test_list_mockup_protocols(sandbox: Sandbox): + """Executes `tezos-client list mockup protocols` + The call must succeed and return a non empty list. + """ + try: + client = sandbox.create_client() + protocols = client.list_mockup_protocols().mockup_protocols + assert protocols + finally: + shutil.rmtree(client.base_dir) + + +@pytest.mark.client +def test_create_mockup_dir_exists_nonempty(sandbox: Sandbox): + """Executes `tezos-client --base-dir /tmp/mdir create mockup` + when /tmp/mdir is a non empty directory which is NOT a mockup + directory. The call must fail. + """ + with tempfile.TemporaryDirectory(prefix='tezos-client.') as base_dir: + # Make the directory not empty + with open(os.path.join(base_dir, "whatever"), "w") as handle: + handle.write("") + unmanaged_client = sandbox.create_client(base_dir=base_dir) + res = unmanaged_client.create_mockup( + protocol=protocol.HASH, check=False + ).create_mockup_result + assert res == CreateMockupResult.DIR_NOT_EMPTY + + +@pytest.mark.client +def test_retrieve_addresses(mockup_client: Client): + """Retrieves known addresses of a fresh mockup. + The call must succeed. + """ + addresses = mockup_client.get_known_addresses().wallet + assert addresses == { + 'bootstrap1': 'tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx', + 'bootstrap2': 'tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN', + 'bootstrap3': 'tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU', + 'bootstrap4': 'tz1b7tUupMgCNw2cCLpKTkSD1NZzB5TkP2sv', + 'bootstrap5': 'tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv', + } + + +@pytest.mark.client +def test_create_mockup_already_initialized(mockup_client: Client): + """Executes `tezos-client --base-dir /tmp/mdir create mockup` + when /tmp/mdir is not fresh. + The call must fail. + """ + # mockup was created already by fixture, try to create it second time: + res = mockup_client.create_mockup( + protocol=protocol.HASH, check=False + ).create_mockup_result + # it should fail: + assert res == CreateMockupResult.ALREADY_INITIALIZED + + +@pytest.mark.client +def test_transfer(mockup_client: Client): + """Executes `tezos-client --base-dir /tmp/mdir -M mockup + transfer 1 from bootstrap1 to bootstrap2` + in a valid mockup environment. + The call must succeed and the balances must be updated correctly. + """ + giver = "bootstrap1" + receiver = "bootstrap2" + transferred = 1.0 + + giver_balance_before = mockup_client.get_balance(giver) + receiver_balance_before = mockup_client.get_balance(receiver) + mockup_client.transfer(transferred, giver, receiver) + giver_balance_after = mockup_client.get_balance(giver) + receiver_balance_after = mockup_client.get_balance(receiver) + + assert giver_balance_after < giver_balance_before - transferred + assert receiver_balance_after == receiver_balance_before + transferred + + +# It's impossible to guess values of chain_id, these ones have been +# obtained by looking at the output of `compute chain id from seed` +@pytest.mark.parametrize( + 'chain_id', + [ + "NetXcqTGZX74DxG", + "NetXaFDF7xZQCpR", + "NetXkKbtqncJcAz", + "NetXjjE5cZUeWPy", + "NetXi7C1pyLhQNe", + ], +) +@pytest.mark.parametrize( + 'initial_timestamp', ["2020-07-21T17:11:10+02:00", "1970-01-01T00:00:00Z"] +) +@pytest.mark.client +def test_create_mockup_custom_constants( + sandbox: Sandbox, chain_id: str, initial_timestamp: str +): + """Tests `tezos-client create mockup` --protocols-constants argument + The call must succeed. + + Args: + mockup_client: the client to use + chain_id (str): the string to pass for field `chain_id` + initial_timestamp(str): an ISO-8601 formatted date string + """ + # Use another directory so that the constants change takes effect + with tempfile.TemporaryDirectory( + prefix='tezos-client.' + ) as base_dir, tempfile.NamedTemporaryFile( + prefix='tezos-custom-constants', mode='w+t' + ) as json_file: + json_data = { + "hard_gas_limit_per_operation": "400000", + "chain_id": chain_id, + "initial_timestamp": initial_timestamp, + } + json.dump(json_data, json_file) + json_file.flush() + unmanaged_client = sandbox.create_client(base_dir=base_dir) + res = unmanaged_client.create_mockup( + protocol=protocol.HASH, protocol_constants_file=json_file.name + ).create_mockup_result + assert res == CreateMockupResult.OK + + +def _create_accounts_list(): + """ + Returns a list of dictionary with 3 entries, that are + valid for being translated to json and passed + to `--bootstrap-accounts` + """ + accounts_list = [] + + def add_account(name: str, sk_uri: str, amount: str): + entry = { + "name": name, + "sk_uri": "unencrypted:" + sk_uri, + "amount": amount, + } + accounts_list.append(entry) + + # Took json structure from + # https://gitlab.com/tezos/tezos/-/merge_requests/1720 + add_account( + "bootstrap0", + "edsk2uqQB9AY4FvioK2YMdfmyMrer5R8mGFyuaLLFfSRo8EoyNdht3", + "2000000000000", + ) + add_account( + "bootstrap1", + "edsk3gUfUPyBSfrS9CCgmCiQsTCHGkviBDusMxDJstFtojtc1zcpsh", + "1000000000000", + ) + + return accounts_list + + +@pytest.mark.client +def test_create_mockup_custom_bootstrap_accounts(sandbox: Sandbox): + """Tests `tezos-client create mockup` --bootstrap-accounts argument + The call must succeed. + """ + accounts_list = _create_accounts_list() + + # Use another directory so that the constants change takes effect + with tempfile.TemporaryDirectory( + prefix='tezos-client.' + ) as base_dir, tempfile.NamedTemporaryFile( + prefix='tezos-bootstrap-accounts', mode='w+t' + ) as json_file: + json.dump(accounts_list, json_file) + json_file.flush() + # Follow pattern of mockup_client fixture: + unmanaged_client = sandbox.create_client(base_dir=base_dir) + res = unmanaged_client.create_mockup( + protocol=protocol.HASH, bootstrap_accounts_file=json_file.name + ).create_mockup_result + assert res == CreateMockupResult.OK + mock_client = sandbox.create_client(base_dir=base_dir, mode="mockup") + addresses_result = mock_client.get_known_addresses() + names_sent = sorted([account["name"] for account in accounts_list]) + names_witnessed = sorted(list(addresses_result.wallet.keys())) + assert names_sent == names_witnessed + + +@pytest.mark.client +def test_transfer_bad_base_dir(sandbox: Sandbox): + """Executes `tezos-client --base-dir /tmp/mdir create mockup` + when /tmp/mdir looks like a dubious base directory. + Checks that a warning is printed. + """ + try: + unmanaged_client = sandbox.create_client() + res = unmanaged_client.create_mockup( + protocol=protocol.HASH + ).create_mockup_result + assert res == CreateMockupResult.OK + base_dir = unmanaged_client.base_dir + mockup_dir = os.path.join(base_dir, "mockup") + + # A valid mockup has a directory named "mockup", in its directory: + assert os.path.isdir(mockup_dir) + mock_client = sandbox.create_client(base_dir=base_dir, mode="mockup") + # Delete this directory: + shutil.rmtree(mockup_dir) + # And put a file instead: + Path(os.path.join(mockup_dir)).touch() + + # Now execute a command + cmd = ["transfer", "1", "from", "bootstrap1", "to", "bootstrap2"] + (_, err_output, _) = mock_client.run_generic(cmd, check=False) + # See + # https://gitlab.com/tezos/tezos/-/merge_requests/1760#note_329071488 + # for the content being matched + searched = "Some commands .* might not work correctly." + # Witness that warning is printed: + assert re.search( + searched, err_output + ), f"'{searched}' not matched in error output" + finally: + shutil.rmtree(base_dir) + + +@pytest.mark.client +def test_config_show_mockup(mockup_client: Client): + """Executes `tezos-client --mode mockup config show` in + a state where it should succeed. + """ + mockup_client.run_generic(["--protocol", protocol.HASH, "config", "show"]) + + +@pytest.mark.client +def test_config_show_mockup_fail(mockup_client: Client): + """Executes `tezos-client --mode mockup config show` when + base dir is NOT a mockup. It should fail as this is dangerous + (the default base directory could contain sensitive data, + such as private keys) + """ + shutil.rmtree(mockup_client.base_dir) # See test_config_init_mockup_fail + # for a variant of how to make the base dir invalid for the mockup mode + _, _, return_code = mockup_client.run_generic( + ["config", "show"], check=False + ) + + # recreate directory: the cleanup later on expects its existence + os.mkdir(mockup_client.base_dir) + assert return_code != 0 + + +@pytest.mark.client +def test_config_init_mockup(mockup_client: Client): + """Executes `tezos-client config init mockup` in + a state where it should succeed. + """ + # We cannot use NamedTemporaryFile because `config init mockup` + # does not overwrite files. Because NamedTemporaryFile creates the file + # it would make the test fail. + ba_json_file = tempfile.mktemp(prefix='tezos-bootstrap-accounts') + pc_json_file = tempfile.mktemp(prefix='tezos-proto-consts') + # 1/ call `config init mockup` + mockup_client.run( + [ + "--protocol", + protocol.HASH, + "config", + "init", + f"--{_BA_FLAG}", + ba_json_file, + f"--{_PC_FLAG}", + pc_json_file, + ] + ) + + # 2/ Try loading the files, to check they are valid json + with open(ba_json_file) as handle: + json.load(handle) + with open(pc_json_file) as handle: + json.load(handle) + + # Cleanup + os.remove(ba_json_file) + os.remove(pc_json_file) + + +@pytest.mark.client +def test_config_init_mockup_fail(mockup_client: Client): + """Executes `tezos-client config init mockup` when + base dir is NOT a mockup. It should fail as this is dangerous + (the default base directory could contain sensitive data, + such as private keys) + """ + ba_json_file = tempfile.mktemp(prefix='tezos-bootstrap-accounts') + pc_json_file = tempfile.mktemp(prefix='tezos-proto-consts') + cmd = [ + "--protocol", + protocol.HASH, + "config", + "init", + f"--{_BA_FLAG}", + ba_json_file, + f"--{_PC_FLAG}", + pc_json_file, + ] + + # A valid mockup has a directory named "mockup" in its base_dir: + mockup_dir = os.path.join(mockup_client.base_dir, "mockup") + assert os.path.isdir(mockup_dir) + # Delete this directory, so that the base_dir is not a valid mockup + # base dir anymore: + shutil.rmtree(mockup_dir) # See test_config_show_mockup_fail above + # for a variant of how to make the base_dir invalid for the mockup mode + + _, _, return_code = mockup_client.run_generic(cmd, check=False) + assert return_code != 0 + # Check the test doesn't leak directories: + assert not os.path.exists(ba_json_file) + assert not os.path.exists(pc_json_file) + + +def _try_json_loads(flag: str, string: str) -> Any: + """ Converts the given string to a json object """ + try: + return json.loads(string) + except json.JSONDecodeError: + pytest.fail( + f"""Write back of {flag} value is not valid json: +{string}""" + ) + + +def _get_state_using_config_init_mockup(mock_client: Client) -> Tuple[str, str]: + """ + Calls `config init mockup` on a mockup client and returns + the strings of the bootstrap accounts and the protocol + constants + + Note that because this a mockup specific operation, the `mock_client` + parameter must be in mockup mode; do not give a vanilla client. + """ + ba_json_file = tempfile.mktemp(prefix='tezos-bootstrap-accounts') + pc_json_file = tempfile.mktemp(prefix='tezos-proto-consts') + + mock_client.run( + [ + "--protocol", + protocol.HASH, + "config", + "init", + f"--{_BA_FLAG}", + ba_json_file, + f"--{_PC_FLAG}", + pc_json_file, + ] + ) + + with open(ba_json_file) as handle: + ba_str = handle.read() + with open(pc_json_file) as handle: + pc_str = handle.read() + + # Cleanup of tempfile.mktemp + os.remove(ba_json_file) + os.remove(pc_json_file) + + return (ba_str, pc_str) + + +def _get_state_using_config_show_mockup(mock_client: Client) -> Tuple[str, str]: + """ + Calls `--mode mockup config show` on a mockup client and returns + the strings of the bootstrap accounts and the protocol + constants, by parsing standard output. + + Note that because this a mockup specific operation, the `mock_client` + parameter must be in mockup mode; do not give a vanilla client. + """ + + def _find_line_starting_with(strings, searched) -> int: + i = 0 + for string in strings: + if string.startswith(searched): + return i + i += 1 + return -1 + + def _parse_config_init_output(string: str) -> Tuple[str, str]: + """Parses the output of `--mode mockup config init` + and return the json of the bootstrap accounts + and the protocol constants + """ + tagline1 = f"Default value of --{_BA_FLAG}:" + bootstrap_accounts_index = string.find(tagline1) + assert bootstrap_accounts_index >= 0, f"{_BA_FLAG} line not found" + + tagline2 = f"Default value of --{_PC_FLAG}:" + proto_constants_index = string.find(tagline2) + assert proto_constants_index > 0, f"{_PC_FLAG} line not found" + + bc_json = string[ + bootstrap_accounts_index + len(tagline1) : proto_constants_index - 1 + ] + + pc_json = string[proto_constants_index + len(tagline2) + 1 :] + return (bc_json, pc_json) + + stdout = mock_client.run(["--protocol", protocol.HASH, "config", "show"]) + return _parse_config_init_output(stdout) + + +def _test_create_mockup_init_show_roundtrip( + sandbox: Sandbox, + read_initial_state, + read_final_state, + bootstrap_json: Optional[str] = None, + protocol_constants_json: Optional[str] = None, +): + """1/ Creates a mockup, using possibly custom bootstrap_accounts + (as specified by `bootstrap_json`) + 2/ Then execute either `--mode mockup config show` or + `--mode mockup config init` to obtain the mockup's parameters + (parse stdout if `show` is called, + read the files generated by `init` otherwise) + + This is done by executing `read_initial_state` + 3/ Recreate a mockup using the output gathered in 2/ and call + `--mode mockup config show`/`--mode mockup config init` + (this is done by executing `read_final_state`) to check that output + received is similar to output seen in 2. + + This is a roundtrip test. + """ + + ba_file = None + pc_file = None + try: + if protocol_constants_json is not None: + pc_file = tempfile.mktemp(prefix='tezos-proto-consts') + with open(pc_file, 'w') as handle: + handle.write(protocol_constants_json) + + if bootstrap_json is not None: + ba_file = tempfile.mktemp(prefix='tezos-bootstrap-accounts') + with open(ba_file, 'w') as handle: + handle.write(bootstrap_json) + + with tempfile.TemporaryDirectory(prefix='tezos-client.') as base_dir: + # Follow pattern of mockup_client fixture: + unmanaged_client = sandbox.create_client(base_dir=base_dir) + res = unmanaged_client.create_mockup( + protocol=protocol.HASH, + bootstrap_accounts_file=ba_file, + protocol_constants_file=pc_file, + ).create_mockup_result + assert res == CreateMockupResult.OK + mock_client = sandbox.create_client( + base_dir=base_dir, mode="mockup" + ) + (ba_str, pc_str) = read_initial_state(mock_client) + finally: + if pc_file is not None: + os.remove(pc_file) + if ba_file is not None: + os.remove(ba_file) + + # 2/ Check the json obtained is valid by building json objects + ba_sent = _try_json_loads(_BA_FLAG, ba_str) + pc_sent = _try_json_loads(_PC_FLAG, pc_str) + + # Test that the initial mockup call honored the values it received. If + # it didn't, all calls would return the default values all along, and + # everything would seem fine; but it wouldn't be. This was witnessed in + # https://gitlab.com/tezos/tezos/-/issues/938 + if bootstrap_json: + ba_input = json.loads(bootstrap_json) + assert ba_sent == ba_input + if protocol_constants_json: + pc_input = json.loads(protocol_constants_json) + assert pc_sent == pc_input + + # 3/ Pass obtained json to a new mockup instance, to check json + # is valid w.r.t. ocaml encoding + + # Use another directory so that the constants change takes effect + with tempfile.TemporaryDirectory( + prefix='tezos-client.' + ) as base_dir, tempfile.NamedTemporaryFile( + prefix='tezos-bootstrap-accounts', mode='w+t' + ) as ba_json_file, tempfile.NamedTemporaryFile( + prefix='tezos-proto-consts', mode='w+t' + ) as pc_json_file, tempfile.TemporaryDirectory( + prefix='tezos-client.' + ) as base_dir: + + ba_json_file.write(ba_str) + ba_json_file.flush() + pc_json_file.write(pc_str) + pc_json_file.flush() + + with tempfile.TemporaryDirectory(prefix='tezos-client.') as base_dir: + # Follow pattern of mockup_client fixture: + unmanaged_client = sandbox.create_client(base_dir=base_dir) + res = unmanaged_client.create_mockup( + protocol=protocol.HASH, + protocol_constants_file=pc_json_file.name, + bootstrap_accounts_file=ba_json_file.name, + ).create_mockup_result + assert res == CreateMockupResult.OK + mock_client = sandbox.create_client( + base_dir=base_dir, mode="mockup" + ) + # 4/ Retrieve state again + (ba_received_str, pc_received_str) = read_final_state(mock_client) + + # Convert it to json objects (check that json is valid) + ba_received = _try_json_loads(_BA_FLAG, ba_received_str) + pc_received = _try_json_loads(_PC_FLAG, pc_received_str) + + def _gen_assert_msg(flag, sent, received): + result = f"Json sent with --{flag} differs from" + result += " json received" + result += f"\nJson sent is:\n{sent}" + result += f"\nwhile json received is:\n{received}" + + # and finally check that json objects received are the same + # as the ones that were given as input + assert ba_sent == ba_received, _gen_assert_msg( + _BA_FLAG, ba_sent, ba_received + ) + assert pc_sent == pc_received, _gen_assert_msg( + _PC_FLAG, pc_sent, pc_received + ) + + +@pytest.mark.client +@pytest.mark.parametrize( + 'initial_bootstrap_accounts', [None, json.dumps(_create_accounts_list())] +) +@pytest.mark.parametrize( + 'protocol_constants', + [ + None, + json.dumps( + { + 'hard_gas_limit_per_operation': "1040001", + 'hard_storage_limit_per_operation': "60001", + 'cost_per_byte': "251", + 'hard_gas_limit_per_block': "10400001", + 'chain_id': "NetXaFDF7xZQCpR", + 'initial_timestamp': "2020-07-21T17:11:10Z", + } + ), + ], +) +@pytest.mark.parametrize( + 'read_initial_state', + [_get_state_using_config_show_mockup, _get_state_using_config_init_mockup], +) +@pytest.mark.parametrize( + 'read_final_state', + [_get_state_using_config_show_mockup, _get_state_using_config_init_mockup], +) +def test_create_mockup_config_show_init_roundtrip( + sandbox: Sandbox, + initial_bootstrap_accounts, + protocol_constants, + read_initial_state, + read_final_state, +): + """1/ Create a mockup, using possibly custom bootstrap_accounts + (as specified by `initial_bootstrap_json`). + 2/ Then execute either `--mode mockup config show` + or `--mode mockup config init` to obtain the mockup's parameters, + as specified by `read_initial_state`. + 3/ Recreate a mockup using the output gathered in 2/ and call + `read_final_state` to check that output + received is similar to output seen in 2. + + This is a roundtrip test using a matrix. + """ + _test_create_mockup_init_show_roundtrip( + sandbox, + read_initial_state, + read_final_state, + initial_bootstrap_accounts, + protocol_constants, + ) + + +def test_transfer_rpc(mockup_client: Client): + """Variant of test_transfer that uses RPCs to get the balances.""" + giver = "bootstrap1" + receiver = "bootstrap2" + transferred = 1.0 + transferred_mutz = transferred * 1000000 + + def get_balance(tz1): + res = mockup_client.rpc( + 'get', + f'chains/main/blocks/head/' f'context/contracts/{tz1}/balance', + ) + return float(res) + + addresses = mockup_client.get_known_addresses() + giver_tz1 = addresses.wallet[giver] + recvr_tz1 = addresses.wallet[receiver] + giver_balance_before = get_balance(giver_tz1) + receiver_balance_before = get_balance(recvr_tz1) + mockup_client.transfer(transferred, giver, receiver) + giver_balance_after = get_balance(giver_tz1) + receiver_balance_after = get_balance(recvr_tz1) + + assert giver_balance_after < giver_balance_before - transferred_mutz + assert receiver_balance_after == receiver_balance_before + transferred_mutz + + +@pytest.mark.parametrize( + 'protos', + [ + (proto1, proto2) + for proto1 in [protocol.HASH, protocol.PREV_HASH] + for proto2 in [protocol.HASH, protocol.PREV_HASH, ""] + ], +) +@pytest.mark.parametrize( + 'command', + [ + ["config", "show"], + ["config", "init"], + ["list", "known", "addresses"], + ["get", "balance", "for", "bootstrap1"], + ], +) +def test_proto_mix( + sandbox: Sandbox, protos: Tuple[str, str], command: List[str] +): + """ + This test covers 3 cases: + + 1/ When proto's second element equals the first member: + it tests that the command works. + 2/ When proto's second element is empty: + it tests that the correct mockup implementation is picked + (i.e. the one of the first element) and that the command works. + 3/ When protos' second element is not empty and differs from + the first member: it tests + that creating a mockup with a protocol and using it with another + protocol fails. + """ + proto1 = protos[0] + proto2 = protos[1] + with tempfile.TemporaryDirectory(prefix='tezos-client.') as base_dir: + # Follow pattern of mockup_client fixture: + unmanaged_client = sandbox.create_client(base_dir=base_dir) + res = unmanaged_client.create_mockup(protocol=proto1) + assert res.create_mockup_result == CreateMockupResult.OK + mock_client = sandbox.create_client(base_dir=base_dir, mode="mockup") + cmd = (["--protocol", proto2] if proto2 else []) + command + success = (proto2 == proto1) or (not proto2) + (_, _, return_code) = mock_client.run_generic(cmd, check=False) + assert (return_code == 0) == success diff --git a/tests_python/tests_009/test_multinode.py b/tests_python/tests_009/test_multinode.py new file mode 100644 index 0000000000000000000000000000000000000000..6a023e780a74c2693d9ca1caa1aaaf1609c7a2c2 --- /dev/null +++ b/tests_python/tests_009/test_multinode.py @@ -0,0 +1,72 @@ +from typing import List +import pytest +from tools import utils +from client.client import Client + + +BAKE_ARGS = ['--max-priority', '512', '--minimal-timestamp'] + + +# TODO test doesn't pass with n=2 (--bootstrap-treshold?) +@pytest.mark.multinode +@pytest.mark.parametrize("clients", [3], indirect=True) +@pytest.mark.incremental +class TestManualBaking: + """ + For n nodes in sandboxed mode, tests: + . injection of protocol alpha + . check inclusion of transfer and endorsement operations + """ + + def test_level(self, clients: List[Client]): + level = 1 + for client in clients: + assert utils.check_level(client, level) + + def test_bake_and_check_level(self, clients: List[Client]): + level = 2 + for i in range(1, 6): + account = f'bootstrap{i}' + client_i = level % len(clients) + clients[client_i].bake(account, BAKE_ARGS) + for client in clients: + assert utils.check_level(client, level) + level += 1 + + def test_endorse(self, clients: List[Client], session: dict): + endorse = clients[2 % len(clients)].endorse('bootstrap3') + session["endorse_hash"] = endorse.operation_hash + + def test_transfer(self, clients: List[Client], session: dict): + client_id = 3 % len(clients) + transfer = clients[client_id].transfer(500, 'bootstrap1', 'bootstrap3') + session["transfer_hash"] = transfer.operation_hash + + def test_mempool_contains_endorse_and_transfer( + self, clients: List[Client], session + ): + endorse_hash = session["endorse_hash"] + transfer_hash = session["transfer_hash"] + operation_hashes = [endorse_hash, transfer_hash] + for client in clients: + assert utils.check_mempool_contains_operations( + client, operation_hashes + ) + + def test_bake(self, clients: List[Client]): + clients[3 % len(clients)].bake('bootstrap4', BAKE_ARGS) + + def test_block_contains_endorse_and_transfer( + self, clients: List[Client], session + ): + endorse_hash = session["endorse_hash"] + transfer_hash = session["transfer_hash"] + operation_hashes = [endorse_hash, transfer_hash] + for client in clients: + assert utils.check_block_contains_operations( + client, operation_hashes + ) + + def test_balance(self, clients: List[Client]): + bal = clients[0].get_balance('tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx') + assert bal == 3998987.999595 diff --git a/tests_python/tests_009/test_multinode_snapshot.py b/tests_python/tests_009/test_multinode_snapshot.py new file mode 100644 index 0000000000000000000000000000000000000000..71676dabe2d185acd02e235a87571bc40e6b13f5 --- /dev/null +++ b/tests_python/tests_009/test_multinode_snapshot.py @@ -0,0 +1,66 @@ +import time +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox +from . import protocol + + +BAKE_ARGS = ['--max-priority', '512', '--minimal-timestamp'] +PARAMS = constants.NODE_PARAMS + ['--history-mode', 'full'] +LEVEL_A = 10 +LEVEL_B = 20 +GROUP1 = [0] +GROUP2 = [3, 4] + + +@pytest.mark.multinode +@pytest.mark.incremental +@pytest.mark.snapshot +@pytest.mark.slow +class TestMultiNodeSnapshot: + def test_init(self, sandbox: Sandbox): + for i in GROUP1: + sandbox.add_node(i, params=PARAMS) + protocol.activate(sandbox.client(GROUP1[0]), activate_in_the_past=True) + + def test_bake_group1_level_a(self, sandbox: Sandbox): + for _ in range(LEVEL_A - 1): + sandbox.client(GROUP1[0]).bake('bootstrap1', BAKE_ARGS) + sandbox.client(GROUP1[0]).endorse('bootstrap2') + + def test_group1_level_a(self, sandbox: Sandbox, session: dict): + for i in GROUP1: + assert utils.check_level(sandbox.client(i), LEVEL_A) + session['head_hash'] = sandbox.client(GROUP1[0]).get_head()['hash'] + + def test_terminate_group1(self, sandbox: Sandbox): + for i in GROUP1: + sandbox.node(i).terminate() + time.sleep(1) + + def test_export_snapshot(self, sandbox: Sandbox, tmpdir, session: dict): + node_export = sandbox.node(GROUP1[0]) + file = f'{tmpdir}/FILE.full' + head_hash = session['head_hash'] + node_export.snapshot_export(file, params=['--block', head_hash]) + + for i in GROUP2: + sandbox.add_node(i, snapshot=file, params=PARAMS) + + def test_rerun_group1(self, sandbox: Sandbox): + for i in GROUP1: + sandbox.node(i).run() + sandbox.client(i).check_node_listening() + + def test_level(self, sandbox: Sandbox): + for i in GROUP1 + GROUP2: + assert utils.check_level(sandbox.client(i), LEVEL_A) + + def test_bake_group2_level_b(self, sandbox: Sandbox): + for _ in range(LEVEL_B - LEVEL_A): + sandbox.client(GROUP2[0]).bake('bootstrap1', BAKE_ARGS) + sandbox.client(GROUP2[0]).endorse('bootstrap2') + + def test_all_level_c(self, sandbox: Sandbox): + for client in sandbox.all_clients(): + assert utils.check_level(client, LEVEL_B) diff --git a/tests_python/tests_009/test_multinode_storage_reconstruction.py b/tests_python/tests_009/test_multinode_storage_reconstruction.py new file mode 100644 index 0000000000000000000000000000000000000000..7cce0f94a5eb139372c2c90697163c019df27974 --- /dev/null +++ b/tests_python/tests_009/test_multinode_storage_reconstruction.py @@ -0,0 +1,88 @@ +import time +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox +from . import protocol + +BAKE_ARGS = ['--max-priority', '512', '--minimal-timestamp'] +PARAMS = constants.NODE_PARAMS + ['--history-mode', 'full'] +BATCH = 16 + + +@pytest.mark.multinode +@pytest.mark.incremental +@pytest.mark.snapshot +@pytest.mark.slow +class TestMultiNodeStorageReconstruction: + def test_init(self, sandbox: Sandbox): + sandbox.add_node(0, params=PARAMS) + protocol.activate(sandbox.client(0), activate_in_the_past=True) + + def test_bake_node0_level_a(self, sandbox: Sandbox, session: dict): + for _ in range(BATCH - 1): + sandbox.client(0).bake('bootstrap1', BAKE_ARGS) + # time.sleep(2) + session['head_hash'] = sandbox.client(0).get_head()['hash'] + session['head_level'] = sandbox.client(0).get_head()['header']['level'] + + def test_export_snapshot(self, sandbox: Sandbox, session: dict): + node_export = sandbox.node(0) + # TODO: use a directory shared by the nodes instead of the node's dir + file = f'{sandbox.node(0).node_dir}/FILE.full' + session['snapshot_head'] = session['head_hash'] + session['snapshot_level'] = session['head_level'] + node_export.snapshot_export( + file, params=['--block', session['snapshot_head']] + ) + + # Test the `--reconstruct` flag of the `snapshot import` command + def test_import_and_reconstruct(self, sandbox: Sandbox, session: dict): + n0_tmpdir = sandbox.node(0).node_dir + file = f'{n0_tmpdir}/FILE.full' + sandbox.add_node(1, snapshot=file, reconstruct=True) + assert utils.check_level(sandbox.client(1), session['head_level']) + + # Test that all the reconstructed blocks can be + # requested as non-pruned blocks + def test_request_all_blocks_as_not_pruned( + self, sandbox: Sandbox, session: dict + ): + for i in range(session['head_level']): + assert utils.get_block_at_level(sandbox.client(1), i) + + # Test the reconstruct command on a full storage + def test_reconstruct_command(self, sandbox: Sandbox, session: dict): + n0_tmpdir = sandbox.node(0).node_dir + file = f'{n0_tmpdir}/FILE.full' + sandbox.add_node(2, snapshot=file) + assert utils.check_level(sandbox.client(2), session['head_level']) + + # Bake a few blocks + def test_bake_node0_level_b(self, sandbox: Sandbox, session: dict): + for _ in range(BATCH): + sandbox.client(0).bake('bootstrap1', BAKE_ARGS) + # time.sleep(2) + session['head_hash'] = sandbox.client(0).get_head()['hash'] + session['head_level'] = sandbox.client(0).get_head()['header']['level'] + assert utils.check_level(sandbox.client(0), session['head_level']) + assert utils.check_level(sandbox.client(1), session['head_level']) + assert utils.check_level(sandbox.client(2), session['head_level']) + + def test_unavailable_blocks(self, sandbox: Sandbox, session: dict): + # We must fail while requesting those pruned blocks + for i in range(1, session['snapshot_level']): + with pytest.raises(Exception): + utils.get_block_metadata_at_level(sandbox.client(2), i) + + def test_reconstruct_the_storage(self, sandbox: Sandbox): + # Stop, reconstruct the storage and restart the node + sandbox.node(2).terminate() + time.sleep(2) + sandbox.node(2).reconstruct() + sandbox.node(2).run() + assert sandbox.client(2).check_node_listening() + + def test_available_blocks(self, sandbox: Sandbox, session: dict): + # We should now success requesting those reconstructed blocks + for i in range(session['head_level']): + assert utils.get_block_at_level(sandbox.client(2), i) diff --git a/tests_python/tests_009/test_multisig.py b/tests_python/tests_009/test_multisig.py new file mode 100644 index 0000000000000000000000000000000000000000..d3249065dd9d919c6f1ec739a5e38008af87f72a --- /dev/null +++ b/tests_python/tests_009/test_multisig.py @@ -0,0 +1,227 @@ +import pytest +from tools import utils +from client.client import Client + +BAKE_ARGS = ['--max-priority', '512', '--minimal-timestamp'] + + +@pytest.mark.incremental +class TestMultisig: + def test_gen_keys(self, client: Client, session: dict): + session['keys'] = ['foo', 'bar', 'boo'] + sigs = [None, 'secp256k1', 'ed25519'] + for key, sig in zip(session['keys'], sigs): + args = [] if sig is None else ['--sig', sig] + client.gen_key(key, args) + + def test_deploy_multisig(self, client: Client, session: dict): + keys = session['keys'] + client.deploy_msig( + 'msig', 100, 'bootstrap1', 2, keys, ['--burn-cap', '100'] + ) + client.bake('bootstrap1', BAKE_ARGS) + + def test_transfer(self, client: Client, session: dict): + key = session['keys'][0] + session['sig0'] = client.msig_sign_transfer( + 'msig', 10, 'bootstrap2', key + ) + + def test_prepare_msig_transfer(self, client: Client): + client.msig_prepare_transfer('msig', 10, 'bootstrap2') + + def test_prepare_msig_sign(self, client: Client, session: dict): + to_sign = client.msig_prepare_transfer( + 'msig', 10, 'bootstrap2', ['--bytes-only'] + ) + session['sig1'] = client.sign_bytes(to_sign, session['keys'][1]) + session['sig2'] = client.sign_bytes(to_sign, session['keys'][2]) + + def test_transfer_failure(self, client: Client, session: dict): + error_pattern = ( + r"Not enough signatures: " + + r"only 1 signatures were given " + + r"but the threshold is currently 2" + ) + + with utils.assert_run_failure(error_pattern): + client.msig_transfer( + 'msig', 10, 'bootstrap2', 'bootstrap1', [session['sig2']] + ) + + def test_transfer_success(self, client: Client, session: dict): + client.msig_transfer( + 'msig', + 10, + 'bootstrap2', + 'bootstrap1', + [session['sig0'], session['sig2']], + ) + client.bake('bootstrap1', BAKE_ARGS) + + def test_delegate_change(self, client: Client, session: dict): + sig0 = client.msig_sign_set_delegate( + 'msig', 'bootstrap5', session['keys'][0] + ) + to_sign = client.msig_prepare_set_delegate( + 'msig', 'bootstrap5', ['--bytes-only'] + ) + sig2 = client.sign_bytes(to_sign, session['keys'][2]) + client.msig_set_delegate( + 'msig', 'bootstrap5', 'bootstrap1', [sig0, sig2] + ) + client.bake('bootstrap1', BAKE_ARGS) + + def test_delegate_withdraw(self, client: Client, session: dict): + sig0 = client.msig_sign_withdrawing_delegate('msig', session['keys'][0]) + to_sign = client.msig_prepare_withdrawing_delegate( + 'msig', ['--bytes-only'] + ) + + sig1 = client.sign_bytes(to_sign, session['keys'][1]) + client.msig_withdrawing_delegate('msig', 'bootstrap1', [sig0, sig1]) + client.bake('bootstrap1', BAKE_ARGS) + + def test_run_transaction_change_keys_and_threshold( + self, client: Client, session: dict + ): + # test changing the keys and threshold with `run transaction` command + keys = session['keys'] + sig0 = client.msig_sign_setting_threshold( + 'msig', keys[0], 2, [keys[0], keys[2]] + ) + to_sign = client.msig_prepare_setting_threshold( + 'msig', 2, [keys[0], keys[2]], ['--bytes-only'] + ) + sig2 = client.sign_bytes(to_sign, session['keys'][2]) + client.msig_run_transaction('msig', to_sign, 'bootstrap1', [sig0, sig2]) + client.bake('bootstrap1', BAKE_ARGS) + + def test_change_keys_and_threshold(self, client: Client, session: dict): + # test changing the keys and threshold with `set threshold of multisig` + keys = session['keys'] + new_keys = [keys[0], keys[2]] + sig0 = client.msig_sign_setting_threshold('msig', keys[0], 2, new_keys) + to_sign = client.msig_prepare_setting_threshold( + 'msig', 2, new_keys, ['--bytes-only'] + ) + sig2 = client.sign_bytes(to_sign, session['keys'][2]) + client.msig_set_threshold( + 'msig', 2, new_keys, 'bootstrap1', [sig0, sig2] + ) + client.bake('bootstrap1', BAKE_ARGS) + + +@pytest.mark.incremental +class TestMultisigFromAddress: + def test_gen_keys(self, client: Client, session: dict): + session['keys'] = ['foo', 'bar', 'boo'] + sigs = [None, 'secp256k1', 'ed25519'] + for key, sig in zip(session['keys'], sigs): + args = [] if sig is None else ['--sig', sig] + client.gen_key(key, args) + + def test_deploy_multisig(self, client: Client, session: dict): + keys = session['keys'] + deployment = client.deploy_msig( + 'msig2', 100, 'bootstrap1', 2, keys, ['--burn-cap', '100'] + ) + session['msig'] = deployment.contract + client.bake('bootstrap1', BAKE_ARGS) + + def test_transfer(self, client: Client, session: dict): + key = session['keys'][0] + msig = session['msig'] + session['sig0'] = client.msig_sign_transfer(msig, 10, 'bootstrap2', key) + + def test_prepare_msig_transfer(self, client: Client, session: dict): + msig = session['msig'] + client.msig_prepare_transfer(msig, 10, 'bootstrap2') + + def test_prepare_msig_sign(self, client: Client, session: dict): + msig = session['msig'] + to_sign = client.msig_prepare_transfer( + msig, 10, 'bootstrap2', ['--bytes-only'] + ) + session['sig1'] = client.sign_bytes(to_sign, session['keys'][1]) + session['sig2'] = client.sign_bytes(to_sign, session['keys'][2]) + + def test_transfer_failure(self, client: Client, session: dict): + msig = session['msig'] + + def cmd(): + client.msig_transfer( + msig, 10, 'bootstrap2', 'bootstrap1', [session['sig2']] + ) + + error_pattern = ( + r"Not enough signatures: " + + r"only 1 signatures were given " + + r"but the threshold is currently 2" + ) + + with utils.assert_run_failure(error_pattern): + cmd() + + def test_transfer_success(self, client: Client, session: dict): + msig = session['msig'] + client.msig_transfer( + msig, + 10, + 'bootstrap2', + 'bootstrap1', + [session['sig0'], session['sig2']], + ) + client.bake('bootstrap1', BAKE_ARGS) + + def test_delegate_change(self, client: Client, session: dict): + msig = session['msig'] + sig0 = client.msig_sign_set_delegate( + msig, 'bootstrap5', session['keys'][0] + ) + to_sign = client.msig_prepare_set_delegate( + msig, 'bootstrap5', ['--bytes-only'] + ) + sig2 = client.sign_bytes(to_sign, session['keys'][2]) + client.msig_set_delegate(msig, 'bootstrap5', 'bootstrap1', [sig0, sig2]) + client.bake('bootstrap1', BAKE_ARGS) + + def test_delegate_withdraw(self, client: Client, session: dict): + msig = session['msig'] + sig0 = client.msig_sign_withdrawing_delegate(msig, session['keys'][0]) + to_sign = client.msig_prepare_withdrawing_delegate( + msig, ['--bytes-only'] + ) + + sig1 = client.sign_bytes(to_sign, session['keys'][1]) + client.msig_withdrawing_delegate(msig, 'bootstrap1', [sig0, sig1]) + client.bake('bootstrap1', BAKE_ARGS) + + def test_run_transaction_change_keys_and_threshold( + self, client: Client, session: dict + ): + # test changing the keys and threshold with `run transaction` command + msig = session['msig'] + keys = session['keys'] + sig0 = client.msig_sign_setting_threshold( + msig, keys[0], 2, [keys[0], keys[2]] + ) + to_sign = client.msig_prepare_setting_threshold( + msig, 2, [keys[0], keys[2]], ['--bytes-only'] + ) + sig2 = client.sign_bytes(to_sign, session['keys'][2]) + client.msig_run_transaction(msig, to_sign, 'bootstrap1', [sig0, sig2]) + client.bake('bootstrap1', BAKE_ARGS) + + def test_change_keys_and_threshold(self, client: Client, session: dict): + # test changing the keys and threshold with `set threshold of multisig` + msig = session['msig'] + keys = session['keys'] + new_keys = [keys[0], keys[2]] + sig0 = client.msig_sign_setting_threshold(msig, keys[0], 2, new_keys) + to_sign = client.msig_prepare_setting_threshold( + msig, 2, new_keys, ['--bytes-only'] + ) + sig2 = client.sign_bytes(to_sign, session['keys'][2]) + client.msig_set_threshold(msig, 2, new_keys, 'bootstrap1', [sig0, sig2]) + client.bake('bootstrap1', BAKE_ARGS) diff --git a/tests_python/tests_009/test_nonce_seed_revelation.py b/tests_python/tests_009/test_nonce_seed_revelation.py new file mode 100644 index 0000000000000000000000000000000000000000..cd756386aa8f341184367435e609ab2f6e22fa2d --- /dev/null +++ b/tests_python/tests_009/test_nonce_seed_revelation.py @@ -0,0 +1,107 @@ +import time +import pytest +from tools import constants +from launchers.sandbox import Sandbox +from . import protocol + + +BLOCKS_PER_COMMITMENT = protocol.PARAMETERS['blocks_per_commitment'] +BLOCKS_PER_CYCLE = protocol.PARAMETERS['blocks_per_cycle'] +FIRST_PROTOCOL_BLOCK = 1 +TIMEOUT = 60 + + +@pytest.mark.incremental +@pytest.mark.slow +@pytest.mark.baker +class TestNonceSeedRevelation: + """Test baker injection of nonce revelations. + + See http://tezos.gitlab.io/008/proof_of_stake.html + + Runs a node and a baker. The baker bakes two full cycles. + We collect nonce hashes from the first cycle. And check + that they are revealed in the second cycle""" + + def test_init(self, sandbox: Sandbox): + """Run a node and a baker. + + The node runs in archive mode to get metadata in `client.get_block()`. + The protocol is activated in the past so the baker can submit blocks + immediately without waiting for current time.""" + + node_params = constants.NODE_PARAMS + ['--history-mode', 'archive'] + sandbox.add_node(0, params=node_params) + protocol.activate(sandbox.client(0), activate_in_the_past=True) + sandbox.add_baker(0, 'bootstrap1', proto=protocol.DAEMON) + + @pytest.mark.timeout(TIMEOUT) + def test_wait_for_two_cycles(self, sandbox: Sandbox): + """Poll the node until target level is reached """ + target = FIRST_PROTOCOL_BLOCK + 2 * BLOCKS_PER_CYCLE + while True: + time.sleep(3) # sleep first to avoid useless first query + if sandbox.client(0).get_level() >= target: + break + # No need to bake more + sandbox.rm_baker(0, proto=protocol.DAEMON) + + def test_get_all_blocks(self, sandbox: Sandbox, session: dict): + """Retrieve all blocks for two full cycles. """ + blocks = [ + sandbox.client(0).get_block(FIRST_PROTOCOL_BLOCK + i) + for i in range(2 * BLOCKS_PER_CYCLE) + ] + session['blocks'] = blocks + + def test_cycle_alignment(self, session): + """Test cycles start where they are supposed to start. + + Not really needed but helps clarifying cycles positions.""" + + blocks = session['blocks'] + # blocks[0] is considered cycle = 0, cycle_position = 0 for the new + # protocol, but because it is a protocol transition block, it + # doesn't have the "cycle" and "cycle_position" metadata (unlike + # the remaining blocks) + assert blocks[1]['metadata']['level']['cycle'] == 0 + assert blocks[1]['metadata']['level']['cycle_position'] == 1 + assert blocks[BLOCKS_PER_CYCLE]['metadata']['level']['cycle'] == 1 + assert ( + blocks[BLOCKS_PER_CYCLE]['metadata']['level']['cycle_position'] == 0 + ) + + def test_collect_seed_nonce_hashes(self, session): + """Collect nonce hashes in the block headers in the first cycle """ + seed_nonce_hashes = {} + blocks = session['blocks'] + for i in range(BLOCKS_PER_CYCLE // BLOCKS_PER_COMMITMENT): + level = (i + 1) * BLOCKS_PER_COMMITMENT - 1 + seed_nonce_hash = blocks[level]['header']['seed_nonce_hash'] + seed_nonce_hashes[level] = seed_nonce_hash + session['seed_nonce_hashes'] = seed_nonce_hashes + + def test_check_revelations(self, session): + """Collect reveal ops in second cycle and check they match + the nonce hashes from first cycle.""" + blocks = session['blocks'] + seed_nonce_hashes = session['seed_nonce_hashes'] + ops = [] + # collect all operations + for i in range(BLOCKS_PER_CYCLE, 2 * BLOCKS_PER_CYCLE): + ops.extend(blocks[i]['operations'][2]) + reveal_ops = {} + for operation in ops: + content = operation['contents'][0] + # there should be only revelations there + assert content['kind'] == "seed_nonce_revelation" + level = content['level'] - FIRST_PROTOCOL_BLOCK + # Can't submit twice the same reveal op + assert level not in reveal_ops + # level should match a seed + assert level in seed_nonce_hashes + reveal_ops[level] = content['nonce'] + + # check all nonce hashes have been revealed + assert len(reveal_ops) == len(seed_nonce_hashes) + # we could go a step further and check that revelations are correct diff --git a/tests_python/tests_009/test_openapi.py b/tests_python/tests_009/test_openapi.py new file mode 100644 index 0000000000000000000000000000000000000000..321c09a1a6fe2b1b707142b735e090543a2aada9 --- /dev/null +++ b/tests_python/tests_009/test_openapi.py @@ -0,0 +1,95 @@ +""" Tests generating the implementation of openapi/swagger: + https://swagger.io/ + + This script launches a sandbox node, activates folder specific + protocol, gets the RPC descriptions as JSON, and converts this JSON + into an OpenAPI specification. + + This test mimicks src/openapi/generate.sh. +""" + +import json +import os +import subprocess +import tempfile +import requests +from launchers.sandbox import Sandbox +from tools.constants import NODE_PARAMS + +from . import protocol + + +def _get_version() -> str: + cmd = ["ocaml", "../scripts/print_version.ml"] + print(" ".join(cmd)) + process_ret = subprocess.run( + cmd, check=True, capture_output=True, text=True + ) + return process_ret.stdout.strip() + + +def _write_file(path: str, content: str): + with open(path, 'w') as handle: + handle.write(content) + + +def _try_json_loads(addr: str, content: str): + """ + `addr` is the address from which `content` was obtained. `addr` + is only used for generating a faulty's assert message. + """ + try: + json.loads(content) + except json.JSONDecodeError: + assert False, f"{addr} did not return valid json" + + +def test_openapi(sandbox: Sandbox): + """Mimicks the script src/openapi/generate.sh. Generates the API + and check it generates valid json.""" + node_idx = 0 + sandbox.add_node(0, params=NODE_PARAMS) + node = sandbox.node(node_idx) + + client = sandbox.client(0) + protocol.activate(client) + + api_addr = f"http://localhost:{node.rpc_port}/describe/?recurse=yes" + api = requests.get(api_addr).text + _try_json_loads(api_addr, api) + + proto_api_addr = ( + f"http://localhost:{node.rpc_port}" + + "/describe/chains/main/blocks/head?recurse=yes" + ) + proto_api = requests.get(proto_api_addr).text + _try_json_loads(proto_api_addr, proto_api) + + version = _get_version() + assert version, "version should not be empty" + + with tempfile.TemporaryDirectory(prefix='tezos-openapi-') as base_dir: + api_path = os.path.join(base_dir, "api.json") + proto_api_path = os.path.join(base_dir, "proto_api.json") + + for (path, content) in [(api_path, api), (proto_api_path, proto_api)]: + _write_file(path, content) + + for input_ in [api_path, proto_api_path]: + # If you need to debug, insert time.sleep(15) in there, + # to give you time to inspect generated files before the + # enclosing 'with' block finishes or to execute the dune + # command manually while the temporary files are still there. + cmd = [ + "dune", + "exec", + "../src/openapi/rpc_openapi.exe", + "--", + version, + input_, + ] + print(" ".join(cmd)) + process_ret = subprocess.run( + cmd, check=True, capture_output=True, text=True + ) + _try_json_loads(" ".join(cmd), process_ret.stdout) diff --git a/tests_python/tests_009/test_p2p.py b/tests_python/tests_009/test_p2p.py new file mode 100644 index 0000000000000000000000000000000000000000..d32da3e803742e94223226d9043cdf05b3db582c --- /dev/null +++ b/tests_python/tests_009/test_p2p.py @@ -0,0 +1,147 @@ +import time +import pytest +from tools import constants +from launchers.sandbox import Sandbox + + +NUM_NODES = 5 +NUM_RETRIES = 20 # empirical values for testing a liveness property +POLLING_TIME = 10 # NUM_RETRY * POLLING_TIME = 200s, should be conservative + + +@pytest.mark.multinode +@pytest.mark.incremental +class TestTrustedRing: + """This test sets up a network of public peers (running the default + p2p protocol), with no initial bootstrap peers. It initializes a + trusted ring relationship, and checks that points are advertised + correctly to the whole network.""" + + def test_init(self, sandbox: Sandbox): + for i in range(NUM_NODES): + sandbox.add_node( + i, + private=False, + peers=[], + params=constants.NODE_PARAMS, + config_client=False, + ) + + def test_no_peers(self, sandbox: Sandbox): + """ Initially, nobody knows other peers. """ + for client in sandbox.all_clients(): + res = client.p2p_stat() + assert not res.peers + + def test_add_peers(self, sandbox: Sandbox): + """ Set up a trusted ring topology. """ + base_p2p = sandbox.p2p + for i in range(NUM_NODES): + client = sandbox.client(i) + client.trust_peer(base_p2p + ((i + 1) % NUM_NODES)) + + def test_check_clique(self, sandbox: Sandbox): + """Everyone should be connected to everyone else. This is a + liveness property. Its realization depends on the timing of the + p2p maintenance process. The check is repeated up to NUM_RETRIES + times with a POLLING_TIME seconds wait.""" + for i in range(NUM_NODES): + client = sandbox.client(i) + for _ in range(NUM_RETRIES): + points = client.p2p_stat().points.values() + num_connected = len( + [point for point in points if point.is_connected] + ) + if num_connected == NUM_NODES - 1: + break + time.sleep(POLLING_TIME) + assert num_connected == NUM_NODES - 1 + + def test_check_tables(self, sandbox: Sandbox): + """Test various assumptions on the point/peer tables. + Each peer has exactly one trusted neighbor. Tables don't + contain their own peer/point id and contain exactly NUM_NODES - 1 + values. + + The previous test should guarantee that maintenance has been + performed when this test is run.""" + base_p2p = sandbox.p2p + for i in range(NUM_NODES): + client = sandbox.client(i) + point_id = f'127.0.0.1:{base_p2p + i}' + peer_id = client.rpc('get', '/network/self') + res = client.p2p_stat() + assert peer_id not in res.peers + assert point_id not in res.points + num_trusted = 0 + for point_id, point in res.points.items(): + num_trusted += point.is_trusted + assert num_trusted == 1 + assert len(res.peers) == NUM_NODES - 1 + assert len(res.points) == NUM_NODES - 1 + + def test_set_expected_peers(self, sandbox: Sandbox): + """For all nodes, we add one expected peer_id + for the successor node.""" + peers_id = dict() + for i in range(NUM_NODES): + client = sandbox.client(i) + peers_id[i] = client.rpc('get', '/network/self') + + for i in range(NUM_NODES): + client = sandbox.client(i) + client.set_expected_peer_id( + sandbox.p2p + ((i + 1) % NUM_NODES), + peers_id[(i + 1) % NUM_NODES], + ) + + def test_expected_peers(self, sandbox: Sandbox): + """For all nodes, we check that expected peer_id was + set properly.""" + peers_id = dict() + for i in range(NUM_NODES): + client = sandbox.client(i) + peers_id[i] = client.rpc('get', '/network/self') + + for i in range(NUM_NODES): + client = sandbox.client(i) + expected_id = client.get_expected_peer_id( + sandbox.p2p + ((i + 1) % NUM_NODES) + ) + assert expected_id == peers_id[(i + 1) % NUM_NODES] + + def test_wrong_expected_peer(self, sandbox: Sandbox): + """We change the expected peer_id set previously to a wrong + expected peer_id.""" + peers_id = dict() + for i in range(NUM_NODES): + client = sandbox.client(i) + peers_id[i] = client.rpc('get', '/network/self') + + for i in range(NUM_NODES): + client = sandbox.client(i) + client.set_expected_peer_id( + sandbox.p2p + ((i + 2) % NUM_NODES), peers_id[i] + ) + + def test_check_stat_with_wrong_expected_peers(self, sandbox: Sandbox): + """All nodes are public, everyone should be connected. But + only one neighbor should be trusted.""" + base_p2p = sandbox.p2p + for i in range(NUM_NODES): + client = sandbox.client(i) + point_id = '127.0.0.1:' + str(base_p2p + i) + peer_id = client.rpc('get', '/network/self') + res = client.p2p_stat() + assert peer_id not in res.peers + assert point_id not in res.points + num_trusted = 0 + num_connected = 0 + for point_id, point in res.points.items(): + num_trusted += point.is_trusted + num_connected += point.is_connected + assert len(res.peers) == NUM_NODES - 1 + assert len(res.points) == NUM_NODES - 1 + assert num_trusted == 1 + # We lost two connections + assert num_connected == NUM_NODES - 1 - 2 diff --git a/tests_python/tests_009/test_perf_endorsement.py b/tests_python/tests_009/test_perf_endorsement.py new file mode 100644 index 0000000000000000000000000000000000000000..cb5e757e2187a3f2ae43e7bf5315f36b62ad54f6 --- /dev/null +++ b/tests_python/tests_009/test_perf_endorsement.py @@ -0,0 +1,74 @@ +import re +import pytest +from client.client import Client +from tools import constants +from . import protocol + +BAKE_ARGS = ['--minimal-timestamp', '--max-priority', '1024'] + +ENDORSING_SLOTS_PER_BLOCK = 2048 +NUM_ACCOUNTS = 256 +ACCOUNTS = [f'bootstrap{i}' for i in range(1, NUM_ACCOUNTS + 1)] +MAX_VALIDATION_TIME_MS = 1000 + + +@pytest.fixture(scope="class") +def client(sandbox): + sandbox.add_node(0, config_client=False, params=constants.NODE_PARAMS) + client = sandbox.client(0) + client.import_secret_key( + 'activator', + 'unencrypted:edsk31vznjHSSpGExDMHYASz45VZqXN4DPxvsa4hAyY8dHM28cZzp6', + ) + bootstrap_accounts = [] + for account in ACCOUNTS: + client.gen_key(account) + address = sandbox.client(0).show_address(account, show_secret=True) + bootstrap_accounts.append([address.public_key, "4000000000000"]) + parameters = dict(protocol.PARAMETERS) + parameters["bootstrap_accounts"] = bootstrap_accounts + parameters["endorsers_per_block"] = ENDORSING_SLOTS_PER_BLOCK + protocol.activate(client, parameters, activate_in_the_past=True) + client.logs = sandbox.logs + yield client + + +@pytest.mark.slow +@pytest.mark.incremental +class TestManualBaking: + """This test bakes a block with NUM_ACCOUNTS endorsers and + check that it takes less than MAX_VALIDATION_TIME_MS to + bake this block. + + MAX_VALIDATION_TIME_MS is conservative to avoid + spurious fails due to slow CI.""" + + def test_endorse(self, client: Client): + client.bake('bootstrap1', BAKE_ARGS) + for account in ACCOUNTS: + client.endorse(account) + client.bake('bootstrap1', BAKE_ARGS) + + def test_check_baking_time_from_log(self, client): + assert client.logs, 'test must be run with "--log-dir LOG_DIR: option' + file = client.logs[0] + # pattern = r"completed in ?(\w*)ms" + pattern = r"validator.block.*completed in ?(.*)s" + time = [] + with open(file, "r") as stream: + for line in stream: + match = re.search(pattern, line) + if match is not None: + time.append(match.groups()[0]) + # 3 blocks have been baked in this test + # . protocol injection + # . empty block + # . block with endorsers + assert len(time) == 3 + endorser_block_time = time[-1] + # log format may use s or ms unit + if endorser_block_time[-1] == 'm': + endorser_block_time_ms = float(endorser_block_time[:-2]) + else: + endorser_block_time_ms = float(endorser_block_time[:-1]) * 1000 + assert float(endorser_block_time_ms) < MAX_VALIDATION_TIME_MS diff --git a/tests_python/tests_009/test_programs.py b/tests_python/tests_009/test_programs.py new file mode 100644 index 0000000000000000000000000000000000000000..c4447152c06a362e0a793d047956a5633f9badf7 --- /dev/null +++ b/tests_python/tests_009/test_programs.py @@ -0,0 +1,98 @@ +import itertools +from client.client import Client + +BAKE_ARGS = ['--minimal-timestamp'] +CONVERT_INPUT_FORMATS = ["michelson", "json", "binary"] +CONVERT_OUTPUT_FORMATS = ["michelson", "json", "binary", "ocaml"] +CONVERT_SCRIPT = { + "michelson": """{ parameter unit ; + storage unit ; + code { CDR ; + NIL operation ; + SELF ; + PUSH mutez 0 ; + UNIT ; + TRANSFER_TOKENS ; + DUP ; + DIP { CONS } ; + CONS ; + PAIR } }""", + "json": """[ { "prim": "parameter", "args": [ { "prim": "unit" } ] }, + { "prim": "storage", "args": [ { "prim": "unit" } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CDR" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "SELF" }, + { "prim": "PUSH", "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "UNIT" }, { "prim": "TRANSFER_TOKENS" }, + { "prim": "DUP" }, + { "prim": "DIP", "args": [ [ { "prim": "CONS" } ] ] }, + { "prim": "CONS" }, { "prim": "PAIR" } ] ] } ]""", + "binary": "0x02000000300500036c0501036c050202000000210317053d036d03490743036a0000034f034d0321051f0200000002031b031b0342", # pylint: disable=line-too-long # noqa: E501 + "ocaml": "Seq (0, [Prim (1, K_parameter, [Prim (2, T_unit, [], [])], []); Prim (3, K_storage, [Prim (4, T_unit, [], [])], []); Prim (5, K_code, [Seq (6, [Prim (7, I_CDR, [], []); Prim (8, I_NIL, [Prim (9, T_operation, [], [])], []); Prim (10, I_SELF, [], []); Prim (11, I_PUSH, [Prim (12, T_mutez, [], []); Int (13, Z.zero)], []); Prim (14, I_UNIT, [], []); Prim (15, I_TRANSFER_TOKENS, [], []); Prim (16, I_DUP, [], []); Prim (17, I_DIP, [Seq (18, [Prim (19, I_CONS, [], [])])], []); Prim (20, I_CONS, [], []); Prim (21, I_PAIR, [], [])])], [])])", # pylint: disable=line-too-long # noqa: E501 +} +CONVERT_DATA = { + "michelson": """{ DROP ; + PUSH address "tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU" ; + CONTRACT unit ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + PUSH mutez 1 ; + UNIT ; + TRANSFER_TOKENS ; + DIP { NIL operation } ; + CONS }""", + "json": """[ { "prim": "DROP" }, + { "prim": "PUSH", + "args": + [ { "prim": "address" }, + { "string": "tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU" } ] }, + { "prim": "CONTRACT", "args": [ { "prim": "unit" } ] }, + [ { "prim": "IF_NONE", + "args": [ [ [ { "prim": "UNIT" }, { "prim": "FAILWITH" } ] ], [] ] } ], + { "prim": "PUSH", "args": [ { "prim": "mutez" }, { "int": "1" } ] }, + { "prim": "UNIT" }, { "prim": "TRANSFER_TOKENS" }, + { "prim": "DIP", + "args": [ [ { "prim": "NIL", "args": [ { "prim": "operation" } ] } ] ] }, + { "prim": "CONS" } ]""", + "binary": "0x020000006403200743036e0100000024747a31666173774354446369527a45346f4a396a6e32566d3264766a6579413966557a550555036c0200000015072f02000000090200000004034f032702000000000743036a0001034f034d051f0200000004053d036d031b", # pylint: disable=line-too-long # noqa: E501 + "ocaml": "Seq (0, [Prim (1, I_DROP, [], []); Prim (2, I_PUSH, [Prim (3, T_address, [], []); String (4, \"tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU\")], []); Prim (5, I_CONTRACT, [Prim (6, T_unit, [], [])], []); Seq (7, [Prim (8, I_IF_NONE, [Seq (9, [Seq (10, [Prim (11, I_UNIT, [], []); Prim (12, I_FAILWITH, [], [])])]); Seq (13, [])], [])]); Prim (14, I_PUSH, [Prim (15, T_mutez, [], []); Int (16, Z.one)], []); Prim (17, I_UNIT, [], []); Prim (18, I_TRANSFER_TOKENS, [], []); Prim (19, I_DIP, [Seq (20, [Prim (21, I_NIL, [Prim (22, T_operation, [], [])], [])])], []); Prim (23, I_CONS, [], [])])", # pylint: disable=line-too-long # noqa: E501 + "type": "lambda unit (list operation)", +} + + +class TestProgramsCommands: + def test_convert_script(self, client: Client): + for (input_, output) in itertools.product( + CONVERT_INPUT_FORMATS, CONVERT_OUTPUT_FORMATS + ): + result = client.run( + [ + "convert", + "script", + CONVERT_SCRIPT[input_], + "from", + input_, + "to", + output, + ] + ) + assert result.strip() == f"{CONVERT_SCRIPT[output]}" + + def test_convert_data(self, client: Client): + for (input_, output, typecheck) in itertools.product( + CONVERT_INPUT_FORMATS, CONVERT_OUTPUT_FORMATS, [True, False] + ): + args = [ + "convert", + "data", + CONVERT_DATA[input_], + "from", + input_, + "to", + output, + ] + if typecheck: + args += ["--type", CONVERT_DATA["type"]] + result = client.run(args) + assert result.strip() == f"{CONVERT_DATA[output]}" diff --git a/tests_python/tests_009/test_proto_demo_counter.py b/tests_python/tests_009/test_proto_demo_counter.py new file mode 100644 index 0000000000000000000000000000000000000000..cd433a91e1a58a3dd57ea018911e42788e7b8c93 --- /dev/null +++ b/tests_python/tests_009/test_proto_demo_counter.py @@ -0,0 +1,89 @@ +import time +import pytest +from tools import constants +from client.client import Client + +PROTO = 'ProtoDemoCounterDemoCounterDemoCounterDemoCou4LSpdT' +PROTO_GENESIS = 'ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im' +PARAMS = ['-p', PROTO_GENESIS] + + +@pytest.fixture(scope="class") +def client(sandbox): + """One node with genesis.""" + sandbox.add_node(0, params=constants.NODE_PARAMS) + client = sandbox.client(0) + yield client + + +@pytest.mark.incremental +class TestProtoDemo: + """Activate protocol demo_counter, inject operations and bake block. + + This test relies on the fixture client which launches a single + sandboxed node. + """ + + def test_proto_known(self, client: Client): + res = client.list_protocols() + assert PROTO in res + + def test_proto_client_known(self, client: Client): + res = client.list_understood_protocols() + assert 'ProtoDemoCou' in res + + def test_first_protocol(self, client: Client): + proto = 'PrihK96nBAFSxVL1GLJTVhu9YnzkMFiBeuJRPA8NwuZVZCE1L6i' + assert client.get_protocol() == proto + + def test_activate_proto(self, client: Client): + parameters = {'init_a': 100, 'init_b': 100} + res = client.activate_protocol_json( + PROTO, parameters, key='activator', fitness='1' + ) + assert res.block_hash + + def test_level1(self, client: Client): + assert client.get_level() == 1 + + def test_protocol_genesis(self, client: Client): + assert client.get_protocol() == PROTO_GENESIS + + def test_bake_command(self, client: Client): + time.sleep(1) + client.run(['bake', 'This is block 2']) + + def test_level2(self, client: Client): + head = client.rpc('get', '/chains/main/blocks/head/') + assert head['header']['level'] == 2 + + def test_inject_operations(self, client: Client): + client.run(['increment', 'a']) + client.run(['increment', 'b']) + client.run(['transfer', '10']) + + def test_mempool(self, client: Client): + ops = client.get_mempool() + assert len(ops['applied']) == 3 + + def test_bake_command_2(self, client: Client): + time.sleep(1) + client.run(['bake', 'This is block 3']) + + def test_level3(self, client: Client): + head = client.rpc('get', '/chains/main/blocks/head/') + assert head['header']['level'] == 3 + + def test_rpc_counter_a(self, client: Client): + head = client.rpc('get', '/chains/main/blocks/head/counter/a') + assert head == 91 + + def test_rpc_counter_b(self, client: Client): + head = client.rpc('get', '/chains/main/blocks/head/counter/b') + assert head == 111 + + def test_get_counter_commands(self, client: Client): + message_a = client.run(['get', 'a']) + assert message_a == "The counter value is 91\n" + message_b = client.run(['get', 'b']) + assert message_b == "The counter value is 111\n" diff --git a/tests_python/tests_009/test_proto_demo_noops_manual_bake.py b/tests_python/tests_009/test_proto_demo_noops_manual_bake.py new file mode 100644 index 0000000000000000000000000000000000000000..fc9eb85aab18cb3b93a102e5373976e74cdc61ff --- /dev/null +++ b/tests_python/tests_009/test_proto_demo_noops_manual_bake.py @@ -0,0 +1,95 @@ +import time +import pytest +from client.client import Client + +PROTO = 'ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp' +PROTO_GENESIS = 'ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im' +PARAMS = ['-p', PROTO_GENESIS] + + +@pytest.fixture(scope="class") +def client(sandbox): + """One node with genesis.""" + sandbox.add_node(0) + client = sandbox.client(0) + yield client + + +def forge_block_header_data(protocol_data): + """ + Returns a binary encoding for a dict of the form + `{'block_header_data: string}`, as expected by the protocol. + + This corresponds to the encoding given by + `data_encoding.(obj1 (req "block_header_data" string))`. See + `lib_data_encoding/data_encoding.mli` for the spec. + """ + assert len(protocol_data) == 1 and 'block_header_data' in protocol_data + string = protocol_data['block_header_data'] + tag = '0000' + padded_hex_len = f'{len(string):#06x}'[2:] + return tag + padded_hex_len + bytes(string, 'utf-8').hex() + + +@pytest.mark.incremental +class TestProtoDemo: + """Activate protocol demo_noops, injection some operations and bake block. + + This test relies on the fixture client which launches a single + sandboxed node. + """ + + def test_proto_known(self, client: Client): + res = client.list_protocols() + assert PROTO in res + + def test_first_protocol(self, client: Client): + proto = 'PrihK96nBAFSxVL1GLJTVhu9YnzkMFiBeuJRPA8NwuZVZCE1L6i' + assert client.get_protocol() == proto + + def test_activate_proto(self, client: Client): + parameters = {} # type: dict + res = client.activate_protocol_json( + PROTO, parameters, key='activator', fitness='1' + ) + assert res.block_hash + + def test_level1(self, client: Client): + assert client.get_level(params=PARAMS) == 1 + + def test_protocol_genesis(self, client: Client): + assert client.get_protocol(params=PARAMS) == PROTO_GENESIS + + def test_manual_bake(self, client: Client): + time.sleep(1) + message = "hello world" + + data = { + "protocol_data": {"protocol": PROTO, "block_header_data": message}, + "operations": [], + } + block = client.rpc( + 'post', + '/chains/main/blocks/head/helpers/preapply/block', + data=data, + params=PARAMS, + ) + + protocol_data = {'block_header_data': message} + encoded = forge_block_header_data(protocol_data) + + shell_header = block['shell_header'] + shell_header['protocol_data'] = encoded + encoded = client.rpc( + 'post', + '/chains/main/blocks/head/helpers/forge_block_header', + data=shell_header, + params=PARAMS, + ) + + inject = {'data': encoded['block'], 'operations': []} + client.rpc('post', '/injection/block', data=inject, params=PARAMS) + + def test_level2(self, client: Client): + head = client.rpc('get', '/chains/main/blocks/head/', params=PARAMS) + assert head['header']['level'] == 2 diff --git a/tests_python/tests_009/test_rpc.py b/tests_python/tests_009/test_rpc.py new file mode 100644 index 0000000000000000000000000000000000000000..05496681ca780dc1363836c616cf5f23eecb2c4f --- /dev/null +++ b/tests_python/tests_009/test_rpc.py @@ -0,0 +1,754 @@ +import os +import time +import pytest +from tools import utils, constants +from launchers.sandbox import Sandbox +from . import protocol +from . import contract_paths + +BAKE_ARGS = ['--max-priority', '512', '--minimal-timestamp'] +CHAIN_ID = "main" +BLOCK_ID = "head" +PKH = "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" +PROTOCOL_HASH = protocol.HASH +BLOCK_LEVEL = "3" +LIST_OFFSET = "0" +OPERATION_OFFSET = "0" + + +@pytest.fixture(scope="class") +def session(): + session = dict() + session["implicit_accounts"] = [ + "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "tz1b7tUupMgCNw2cCLpKTkSD1NZzB5TkP2sv", + "tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU", + "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + ] + return session + + +@pytest.fixture(scope="class") +def contract_name(): + return "contract_identity" + + +@pytest.fixture(scope="class", params=[None, "proxy"]) +def sandbox(request, sandbox: Sandbox, contract_name, session: dict): + """Adds two nodes to sandbox. Using the first node, originates the + identity contract `id.tz` with the name contract_name and makes it + address available under session['originated_accounts']. + """ + sandbox.add_node(1, params=constants.NODE_PARAMS, mode=request.param) + sandbox.add_node(2, params=constants.NODE_PARAMS, mode=request.param) + client = sandbox.client(1) + protocol.activate(sandbox.client(1), activate_in_the_past=True) + client.bake("bootstrap1", BAKE_ARGS) + time.sleep(2) + # Deploy a contract + contract = os.path.join(contract_paths.CONTRACT_PATH, 'attic', 'id.tz') + args = ['--init', "\"tezos\"", '--burn-cap', '10.0'] + origination = client.originate( + contract_name, 10.0, "bootstrap1", contract, args + ) + session['originated_accounts'] = [origination.contract] + client.bake("bootstrap1", ["--minimal-timestamp"]) + assert utils.check_block_contains_operations( + client, [origination.operation_hash] + ) + return sandbox + + +@pytest.mark.mempool +@pytest.mark.multinode +@pytest.mark.slow +class TestRPCsExistence: + """ + Tests the existence of RPCs. It does not check the output! + Existence relying on the storage are tested using bootstrap + accounts/originated contracts. + """ + + block_hash = "" + + def test_config_file(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/config') + + def test_network_self(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/network/self') + + def test_constants(self, sandbox: Sandbox): + sandbox.client(2).rpc('get', '/network/self') + sandbox.client(1).bake('bootstrap1', BAKE_ARGS) + time.sleep(3) + + def test_chain_blocks(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', f'/chains/{CHAIN_ID}/blocks') + + def test_chain_chain_id(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', f'/chains/{CHAIN_ID}/chain_id') + + def test_chain_invalid_blocks(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', f'/chains/{CHAIN_ID}/invalid_blocks') + + @pytest.mark.skip(reason="TODO") + def test_chain_invalid_blocks_block_hash(self, sandbox: Sandbox): + res = sandbox.client(1).bake('bootstrap1', BAKE_ARGS) + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/invalid_blocks/' f'{res.block_hash}' + ) + + @pytest.mark.skip + def test_describe(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/describe') + + def test_errors(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/errors') + + def test_fetch_protocol_protocol_hash(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', f'/fetch_protocol/{PROTOCOL_HASH}') + + def test_network_connections(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/network/connections') + + def test_network_connections_peer_id(self, sandbox: Sandbox): + peer_id = sandbox.client(2).rpc('get', '/network/self') + sandbox.client(1).rpc('get', f'/network/connections/{peer_id}') + + def test_network_greylist_clear(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/network/greylist/clear') + + def test_network_peers(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/network/peers') + + def test_network_peers_peer_id(self, sandbox: Sandbox): + peer_id = sandbox.client(2).rpc('get', '/network/self') + sandbox.client(1).rpc('get', f'/network/peers/{peer_id}') + + def test_network_peers_peer_id_ban(self, sandbox: Sandbox): + peer_id = sandbox.client(2).rpc('get', '/network/self') + sandbox.client(1).rpc('get', f'/network/peers/{peer_id}/ban') + + def test_network_peers_peer_id_banned(self, sandbox: Sandbox): + peer_id = sandbox.client(2).rpc('get', '/network/self') + sandbox.client(1).rpc('get', f'/network/peers/{peer_id}/banned') + + def test_network_peers_peer_id_unban(self, sandbox: Sandbox): + peer_id = sandbox.client(2).rpc('get', '/network/self') + sandbox.client(1).rpc('get', f'/network/peers/{peer_id}/unban') + + def test_network_peers_peer_id_untrust(self, sandbox: Sandbox): + peer_id = sandbox.client(2).rpc('get', '/network/self') + sandbox.client(1).rpc('get', f'/network/peers/{peer_id}/untrust') + + def test_network_peers_peer_id_trust(self, sandbox: Sandbox): + peer_id = sandbox.client(2).rpc('get', '/network/self') + sandbox.client(1).rpc('get', f'/network/peers/{peer_id}/trust') + + def test_network_points(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/network/points') + + def test_network_points_point(self, sandbox: Sandbox): + points = sandbox.client(1).rpc('get', '/network/points') + point = points[-1][0] + sandbox.client(1).rpc('get', f'/network/points/{point}') + + def test_network_points_point_ban(self, sandbox: Sandbox): + points = sandbox.client(1).rpc('get', '/network/points') + point = points[-1][0] + sandbox.client(1).rpc('get', f'/network/points/{point}/ban') + + def test_network_points_point_banned(self, sandbox: Sandbox): + points = sandbox.client(1).rpc('get', '/network/points') + point = points[-1][0] + sandbox.client(1).rpc('get', f'/network/points/{point}/banned') + + def test_network_points_point_trust(self, sandbox: Sandbox): + points = sandbox.client(1).rpc('get', '/network/points') + point = points[-1][0] + sandbox.client(1).rpc('get', f'/network/points/{point}/trust') + + def test_network_points_point_unban(self, sandbox: Sandbox): + points = sandbox.client(1).rpc('get', '/network/points') + point = points[-1][0] + sandbox.client(1).rpc('get', f'/network/points/{point}/unban') + + def test_network_points_point_untrust(self, sandbox: Sandbox): + points = sandbox.client(1).rpc('get', '/network/points') + point = points[-1][0] + sandbox.client(1).rpc('get', f'/network/points/{point}/untrust') + + def test_network_stat(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/network/stat') + + def test_network_version(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/network/version') + + def test_network_versions(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/network/versions') + + def test_protocols(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/protocols') + + def test_protocols_protocol_hash(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', f'/protocols/{PROTOCOL_HASH}') + + def test_workers_block_validator(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/workers/block_validator') + + def test_workers_chain_validators(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/workers/chain_validators') + + def test_workers_chain_validator(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', f'/workers/chain_validators/{CHAIN_ID}') + + def test_workers_chain_validator_ddb(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/workers/chain_validators/{CHAIN_ID}/ddb' + ) + + def test_workers_chain_validator_peers_validators(self, sandbox): + sandbox.client(1).rpc( + 'get', f'/workers/chain_validators/{CHAIN_ID}/' 'peers_validators' + ) + + @pytest.mark.skip + def test_workers_chain_validator_peer_validator(self, sandbox: Sandbox): + peer_id = sandbox.client(2).rpc('get', '/network/self') + sandbox.client(1).rpc( + 'get', + f'/workers/chain_validators/{CHAIN_ID}' + f'/peers_validators/{peer_id}', + ) + + def test_workers_prevalidators(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', '/workers/prevalidators') + + def test_workers_prevalidators_chain_id(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', f'/workers/prevalidators/{CHAIN_ID}') + + def test_chain_block(self, sandbox: Sandbox): + sandbox.client(1).rpc('get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}') + + def test_chain_block_context_constants(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'context/constants' + ) + + def test_chain_block_context_constants_errors(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'context/constants/errors', + ) + + def test_chain_block_context_contracts(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'context/contracts' + ) + + def test_chain_block_context_contract_id( + self, sandbox: Sandbox, session: dict + ): + accounts = session["originated_accounts"] + session["implicit_accounts"] + for contract_id in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}', + ) + + def test_chain_block_context_contract_balance( + self, sandbox: Sandbox, session: dict + ): + accounts = session["originated_accounts"] + session["implicit_accounts"] + for contract_id in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/balance', + ) + + def test_chain_block_context_contract_counter( + self, sandbox: Sandbox, session: dict + ): + # only implicit contracts, see + # proto_alpha/lib_protocol/contract_repr.ml + for contract_id in session["implicit_accounts"]: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/counter', + ) + + def test_chain_block_context_contract_delegate( + self, sandbox: Sandbox, session: dict + ): + for contract_id in session["implicit_accounts"]: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/delegate', + ) + + @pytest.mark.skip + # TODO + def test_chain_block_context_contract_manager( + self, sandbox: Sandbox, session: dict + ): + accounts = session["originated_accounts"] + session["implicit_accounts"] + for contract_id in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/manager', + ) + + @pytest.mark.skip(reason="TODO") + def test_chain_block_context_contract_manager_key( + self, sandbox, session: dict + ): + accounts = session["originated_accounts"] + session["implicit_accounts"] + for contract_id in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/' + 'manager_key', + ) + + def test_chain_block_context_contract_script_originated( + self, sandbox: Sandbox, session: dict + ): + # only originated contracts + accounts = session["originated_accounts"] + for contract_id in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/script', + ) + + def test_chain_block_context_contract_script_implicit( + self, sandbox: Sandbox, session: dict + ): + accounts = session["implicit_accounts"] + for contract_id in accounts: + with utils.assert_run_failure('No service found at this URL'): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/' + 'script', + ) + + def test_chain_block_context_contract_storage_originated( + self, sandbox: Sandbox, session: dict + ): + # only originated contracts + accounts = session["originated_accounts"] + for contract_id in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/storage', + ) + + def test_chain_block_context_contract_storage_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit contracts + accounts = session["implicit_accounts"] + for contract_id in accounts: + with utils.assert_run_failure('No service found at this URL'): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/' + 'storage', + ) + + def test_chain_block_context_delegates(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'context/delegates' + ) + + def test_chain_block_context_delegate_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit accounts + accounts = session["implicit_accounts"] + for pkh in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/delegates/{pkh}', + ) + + @pytest.mark.skip("TODO: Expected behaviour for originated, must exist?") + def test_chain_block_context_delegate_originated(self, sandbox: Sandbox): + pass + + def test_chain_block_context_delegate_balance_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit accounts + accounts = session["implicit_accounts"] + for pkh in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/delegates/{pkh}/balance', + ) + + @pytest.mark.skip("TODO: Expected behaviour for originated, must exist?") + def test_chain_block_context_delegate_balance_originated( + self, sandbox: Sandbox + ): + pass + + def test_chain_block_context_delegate_deactivated_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit accounts + accounts = session["implicit_accounts"] + for pkh in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/delegates/{pkh}/deactivated', + ) + + @pytest.mark.skip("TODO: Expected behaviour for originated, must exist?") + def test_chain_block_context_delegate_deactivated_originated( + self, sandbox: Sandbox, session: dict + ): + pass + + def test_chain_block_context_delegate_delegated_balance_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit accounts + accounts = session["implicit_accounts"] + for pkh in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/delegates/{pkh}/delegated_balance', + ) + + @pytest.mark.skip("TODO: Expected behaviour for originated, must exist?") + def test_chain_block_context_delegate_delegated_balance_originated( + self, sandbox: Sandbox, session: dict + ): + pass + + def test_chain_block_context_delegate_delegated_contracts_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit accounts + accounts = session["implicit_accounts"] + for pkh in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/delegates/{pkh}/' + 'delegated_contracts', + ) + + @pytest.mark.skip("TODO: Expected behaviour for originated, must exist?") + def test_chain_block_context_delegate_delegated_contracts_originated( + self, sandbox: Sandbox, session: dict + ): + pass + + def test_chain_block_context_delegate_frozen_balance_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit accounts + accounts = session["implicit_accounts"] + for pkh in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/delegates/{pkh}/frozen_balance', + ) + + @pytest.mark.skip("TODO: Expected behaviour for originated, must exist?") + def test_chain_block_context_delegate_frozen_balance_originated( + self, sandbox: Sandbox, session: dict + ): + pass + + def test_chain_block_context_delegate_frozen_balance_by_cycle_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit accounts + accounts = session["implicit_accounts"] + for pkh in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/delegates/{pkh}/' + 'frozen_balance_by_cycle', + ) + + @pytest.mark.skip("TODO: Expected behaviour for originated, must exist?") + def test_chain_block_context_delegate_frozen_balance_by_cycle_originated( + self, sandbox: Sandbox, session: dict + ): + pass + + def test_chain_block_context_delegate_grace_period_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit accounts + accounts = session["implicit_accounts"] + for pkh in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/delegates/{pkh}/grace_period', + ) + + @pytest.mark.skip("TODO: Expected behaviour for originated, must exist?") + def test_chain_block_context_delegate_grace_period_originated( + self, sandbox: Sandbox, session: dict + ): + pass + + def test_chain_block_context_delegate_staking_balance_implicit( + self, sandbox: Sandbox, session: dict + ): + # only implicit accounts + accounts = session["implicit_accounts"] + for pkh in accounts: + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/delegates/{pkh}/staking_balance', + ) + + @pytest.mark.skip("TODO: Expected behaviour for originated, must exist?") + def test_chain_block_context_delegate_staking_balance_originated( + self, sandbox: Sandbox, session: dict + ): + pass + + def test_chain_block_context_nonces_block_level(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/nonces/{BLOCK_LEVEL}', + ) + + def test_chain_block_context_raw_bytes(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'context/raw/bytes' + ) + + def test_chain_block_hash(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/hash' + ) + + def test_chain_block_header(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'header' + ) + + def test_chain_block_header_protocol_data(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'header/protocol_data', + ) + + def test_chain_block_header_protocol_data_raw(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'header/protocol_data/raw', + ) + + def test_chain_block_header_raw(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'header/raw' + ) + + def test_chain_block_header_shell(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'header/shell' + ) + + def test_chain_block_helpers_baking_rights(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'helpers/baking_rights', + ) + + def test_chain_block_helpers_complete_prefix1(self, sandbox: Sandbox): + prefix = PKH[:10] + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'helpers/complete/{prefix}', + ) + + def test_chain_block_helpers_complete_prefix2(self, sandbox: Sandbox): + res = sandbox.client(1).bake('bootstrap1', BAKE_ARGS) + prefix = res.block_hash[:5] + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'helpers/complete/{prefix}', + ) + + def test_chain_block_helpers_current_level(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'helpers/current_level', + ) + + def test_chain_block_helpers_endorsing_rights(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'helpers/endorsing_rights', + ) + + def test_chain_block_helpers_levels_in_current_cycle( + self, sandbox: Sandbox + ): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + 'helpers/levels_in_current_cycle', + ) + + def test_chain_block_live_blocks(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'live_blocks' + ) + + def test_chain_block_metadata(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'metadata' + ) + + def test_chain_block_operation_hashes(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'operation_hashes' + ) + + def test_add_transactions(self, sandbox: Sandbox): + sandbox.client(1).transfer(1.000, 'bootstrap1', 'bootstrap2') + sandbox.client(2).transfer(1.000, 'bootstrap3', 'bootstrap4') + sandbox.client(1).endorse('bootstrap1') + sandbox.client(1).bake('bootstrap1', BAKE_ARGS) + time.sleep(3) + + def test_chain_block_operation_hashes_list_offset(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'operation_hashes/{LIST_OFFSET}', + ) + + def test_chain_block_operation_hashes_list_operation( + self, sandbox: Sandbox + ): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'operation_hashes/{LIST_OFFSET}/' + f'{OPERATION_OFFSET}', + ) + + def test_chain_block_operations(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'operations' + ) + + def test_chain_block_operations_list(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'operations/{LIST_OFFSET}', + ) + + def test_chain_block_operations_list_operation(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'operations/{LIST_OFFSET}/' + f'{OPERATION_OFFSET}', + ) + + def test_chain_block_votes_ballot_list(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' f'votes/ballot_list' + ) + + def test_chain_block_votes_ballots(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'votes/ballots' + ) + + def test_chain_block_votes_current_period(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'votes/current_period', + ) + + def test_chain_block_votes_current_proposal(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'votes/current_proposal', + ) + + def test_chain_block_votes_current_quorum(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'votes/current_quorum', + ) + + def test_chain_block_votes_listings(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'votes/listings' + ) + + def test_chain_block_votes_proposals(self, sandbox: Sandbox): + sandbox.client(1).rpc( + 'get', f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' 'votes/proposals' + ) + + def test_stat_gc(self, sandbox: Sandbox): + assert sandbox.client(1).rpc('get', "/stats/gc") + + def test_stat_memory(self, sandbox: Sandbox): + assert sandbox.client(1).rpc('get', "/stats/memory") + + +class TestDeprecatedRPCs: + def test_chain_block_context_contract_delegatable( + self, sandbox: Sandbox, session: dict + ): + for contract_id in session["implicit_accounts"]: + with utils.assert_run_failure(r"Did not find service"): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/' + f'{BLOCK_ID}/context/contracts/' + f'{contract_id}/delegatable', + ) + + def test_chain_block_context_contract_spendable( + self, sandbox: Sandbox, session: dict + ): + accounts = session["originated_accounts"] + session["implicit_accounts"] + for contract_id in accounts: + with utils.assert_run_failure(r"Did not find service"): + sandbox.client(1).rpc( + 'get', + f'/chains/{CHAIN_ID}/blocks/{BLOCK_ID}/' + f'context/contracts/{contract_id}/' + 'spendable', + ) diff --git a/tests_python/tests_009/test_sapling.py b/tests_python/tests_009/test_sapling.py new file mode 100644 index 0000000000000000000000000000000000000000..906f098f18e9ca50a926045cb487edc79759b31e --- /dev/null +++ b/tests_python/tests_009/test_sapling.py @@ -0,0 +1,947 @@ +import json +import re +from os import path +import pytest +from tools import utils, paths, constants +from tools.utils import assert_run_failure +from . import contract_paths +from . import protocol + +PROTO = "009_PsFLoren" +CONTRACT_PATH = path.join( + paths.TEZOS_HOME, 'src', f'proto_{PROTO}', 'lib_protocol', 'test' +) +TX_AMOUNT = 100.0 + + +# TODO: Use a random valid memo size for shielded-tez and others +@pytest.fixture +def contract_path(): + return CONTRACT_PATH + + +@pytest.fixture(scope="class") +def sandbox(sandbox): + sandbox.add_node(0, params=constants.NODE_PARAMS) + protocol.activate(sandbox.client(0), activate_in_the_past=True) + return sandbox + + +@pytest.fixture(scope="class") +def node(sandbox): + return sandbox.node(0) + + +@pytest.fixture(scope="class") +def client(sandbox, node): + client = sandbox.get_new_client(node) + return client + + +@pytest.fixture +def mnemonic(): + return [ + "morning", + "dinosaur", + "estate", + "youth", + "sausage", + "feature", + "apology", + "bullet", + "square", + "type", + "zoo", + "coyote", + "extra", + "fabric", + "grain", + "phone", + "pipe", + "despair", + "razor", + "ranch", + "blouse", + "debris", + "urge", + "evidence", + ] + + +@pytest.fixture +def non_originated_contract_address(): + return "KT1MXuZJJFg4EVpLQeLeuHvznTRiNefh3yCs" + + +@pytest.fixture +def non_originated_contract_name(): + return "fake-contract" + + +@pytest.fixture +def key_name(): + return "test_key_name" + + +# here baker 'account' has baked a block and has sent 'tx_amount' +def check_baker_balance(client, account, tx_amount): + parameters = dict(protocol.PARAMETERS) + initial_amount = float(parameters["bootstrap_accounts"][0][1]) + deposit = float(parameters["block_security_deposit"]) + # sender's balance without fees + expected_baker_balance = (initial_amount - deposit) / 1000000 - tx_amount + baker_balance = client.get_balance(account) + # the fees are assumed to be at most 1 tez + assert expected_baker_balance - 1 <= baker_balance <= expected_baker_balance + + +@pytest.mark.client +class TestSaplingWalletImportKey: + @pytest.fixture + def client( + self, + sandbox, + node, + non_originated_contract_name, + non_originated_contract_address, + ): + """ + A client with a pre-registered contract to link the wallet with. + """ + client = sandbox.get_new_client(node) + client.remember_contract( + non_originated_contract_name, non_originated_contract_address + ) + return client + + def test_import_key_no_force(self, client, mnemonic, key_name): + """ + Import key without forcing and without pre-existing alias + """ + client.sapling_import_key(key_name, mnemonic, force=False) + + def test_import_key_force_and_non_previously_saved( + self, + client, + mnemonic, + key_name, + ): + """ + Import key with forcing and without pre-existing alias + """ + client.sapling_import_key(key_name, mnemonic, force=True) + + def test_import_key_force_and_previously_saved( + self, + client, + mnemonic, + key_name, + ): + """ + Import key with forcing and with pre-existing alias + """ + client.sapling_import_key(key_name, mnemonic, force=False) + client.sapling_import_key(key_name, mnemonic, force=True) + + +class TestSaplingWalletAddressGeneration: + @pytest.fixture + def client(self, sandbox, node, key_name, mnemonic): + """ + A client with a sapling wallet + """ + client = sandbox.get_new_client(node) + client.sapling_import_key(key_name, mnemonic, force=False) + return client + + @pytest.mark.parametrize( + "expected_address,expected_index", + [ + ( + "zet13XtyU5Bkasoj1b19sy4DJc7U13XydbxLHqLUdf8Y5tarGb" + "HgFLgDrT6J6FYJoHGL3", + 0, + ) + ], + ) + def test_generate_first_address_of_key( + self, client, key_name, expected_address, expected_index + ): + result = client.sapling_gen_address(key_name) + assert result.index == expected_index + assert result.address == expected_address + + @pytest.mark.parametrize( + "requested_index,expected_address,expected_index", + [ + ( + 0, + "zet13XtyU5Bkasoj1b19sy4DJc7U13XydbxLHqLUdf8Y5tarGb" + "HgFLgDrT6J6FYJoHGL3", + 0, + ), + ( + 1, + "zet13mN26QV67FgPzMSzrigXjKZNMMtCubhi9L3kUePnFYdXqEj" + "c8pmjw1h2wC6NLZf5F", + 1, + ), + ( + 2, + "zet12hzbYRRKbWwKPY61FkjLg7CRWTcjooqeH7VH18fA6Vxnwy7" + "WyTrAEqBXmEdHp9woU", + 4, + ), + ( + 3, + "zet12hzbYRRKbWwKPY61FkjLg7CRWTcjooqeH7VH18fA6Vxnwy7" + "WyTrAEqBXmEdHp9woU", + 4, + ), + ( + 4, + "zet12hzbYRRKbWwKPY61FkjLg7CRWTcjooqeH7VH18fA6Vxnwy7" + "WyTrAEqBXmEdHp9woU", + 4, + ), + ( + 100, + "zet14LmgdAzVrTtQKpeuD3f2y7wFSjXTMEexNNuiEWhGimm25en" + "xkqmwmbdFsC4y6YmYx", + 100, + ), + ( + 143534, + "zet14EWNxZYoHJASHFpcCYSfTfQokWSMzdJeV5SfaGEPDtiYiDC" + "X5jz8QkMF5jZaK5F4k", + 143536, + ), + ( + 42, + "zet143WVQUmNodhSe4ytHL6gvtdXYhRp7bywDWASUFYUCMGAS71" + "juXT6AyWY89fjg3eZn", + 42, + ), + ( + 90870987456348, + "zet13CiUqFsVEr2LdMnyyUQNL3Nh74sa4LdU6V3oD3YfcizbwuF" + "tftPRYvRrB2zsVaEw1", + 90870987456348, + ), + ], + ) + def test_generate_address_with_address_index( + self, + client, + key_name, + expected_address, + expected_index, + requested_index, + ): + result = client.sapling_gen_address(key_name, index=requested_index) + assert result.index == expected_index + assert result.address == expected_address + + +@pytest.mark.client +@pytest.mark.contract +@pytest.mark.incremental +class TestSaplingShieldedTez: + """ + Tests involving sapling key management and shielded transactions using + the shielded tez example contract. + """ + + @pytest.fixture + def contract_path(self): + return path.join(CONTRACT_PATH, 'contracts', 'sapling_contract.tz') + + @pytest.fixture + def contract_name(self): + return "sapling" + + @pytest.fixture(scope="session") + def tmpdir(self, tmpdir_factory): + """ + Temporary directory. Forged transactions will be saved + in this directory. + FIXME/IMPROVEME: tmpdir_factory is a fixture provided by pytest. It is + session-scoped, then the fixture tmpdir must be session-scoped. + Would be nice to have a class-scoped fixture. + """ + tmpdir = tmpdir_factory.mktemp("sapling_transactions_shielded_tez") + return tmpdir + + def test_originate_sapling_contract( + self, contract_path, client, session, contract_name + ): + sender = "bootstrap1" + origination = client.originate( + contract_name=contract_name, + amount=0, + sender=sender, + contract=contract_path, + args=["--init", "{ }", "--burn-cap", "3.0"], + ) + session["contract_address"] = origination.contract + client.bake(sender, ["--minimal-timestamp"]) + assert utils.check_block_contains_operations( + client, + [origination.operation_hash], + ) + + def test_generate_bob(self, client, session, contract_name): + key_name = "bob" + result = client.sapling_gen_key(key_name=key_name) + client.sapling_use_key_for_contract( + key_name, contract_name, memo_size=8 + ) + session['bob_mnemonic'] = result.mnemonic + + def test_list_keys_bob(self, client): + keys = client.sapling_list_keys() + assert keys == ["bob"] + + def test_list_keys_with_alice_and_bob(self, client, contract_name): + """ + NB: another key (ali) is generated in the test, but the mnemonic + is not saved. + We add this test to verify the list keys command orders alphabetically + """ + key_name = "ali" + client.sapling_gen_key(key_name=key_name) + client.sapling_use_key_for_contract( + key_name=key_name, contract_name=contract_name + ) + keys = client.sapling_list_keys() + assert keys == ["ali", "bob"] + + def test_generate_bob_address_0(self, client, session): + result = client.sapling_gen_address( + key_name="bob", + ) + session['last_address_index'] = result.index + session['bob_address_0'] = result.address + + def test_generate_bob_address_1(self, client, session): + result = client.sapling_gen_address( + key_name="bob", + ) + assert result.index > session['last_address_index'] + session['bob_address_1'] = result.address + + def test_check_bob_balance(self, client, contract_name): + result = client.sapling_get_balance( + key_name="bob", + contract_name=contract_name, + ) + assert result.balance == 0 + + def test_shield_bob_address_0(self, client, session, contract_name): + client.sapling_shield( + amount=TX_AMOUNT, + src="bootstrap2", + dest=session['bob_address_0'], + contract=contract_name, + args=["--burn-cap", "3.0"], + ) + client.bake("bootstrap2", ["--minimal-timestamp"]) + check_baker_balance(client, "bootstrap2", TX_AMOUNT) + bob_balance = client.sapling_get_balance( + key_name="bob", contract_name=contract_name + ).balance + assert bob_balance == TX_AMOUNT + + def test_check_contract_balance_after_shielding( + self, client, contract_name + ): + assert client.get_balance(contract_name) == TX_AMOUNT + + def test_regenerate_bob_from_mnemonic(self, client, session): + # Overwrite the old 'bob' key with one restored from the mnemonic. + key_name = "bob" + client.sapling_import_key( + key_name=key_name, + mnemonic=session['bob_mnemonic'], + force=True, + ) + + def test_derive_alice(self, client, contract_name): + result = client.sapling_derive_key( + source_key_name='bob', + target_key_name='alice', + contract_name=contract_name, + index='0', + ) + assert result.path == '0/0' + + def test_derive_yves(self, client, contract_name): + result = client.sapling_derive_key( + source_key_name='bob', + target_key_name='yves', + contract_name=contract_name, + index='1', + ) + assert result.path == '0/1' + + def test_generate_alice_address_0(self, client, session): + result = client.sapling_gen_address( + key_name="alice", + ) + session['alice_address_0'] = result.address + + def test_alice_shields_money_insufficient_funds( + self, client, session, contract_name + ): + with assert_run_failure(r'too low \(4000000\) to spend 2100000000'): + client.sapling_shield( + amount=2100000000.0, + src="bootstrap3", + dest=session['alice_address_0'], + contract=contract_name, + args=["--burn-cap", "3.0"], + ) + + def test_alice_shields_money(self, client, session, contract_name): + client.sapling_shield( + amount=TX_AMOUNT, + src="bootstrap3", + dest=session['alice_address_0'], + contract=contract_name, + args=[ + "--burn-cap", + "3.0", + ], + ) + client.bake("bootstrap3", ["--minimal-timestamp"]) + check_baker_balance(client, "bootstrap3", TX_AMOUNT) + alice_balance = client.sapling_get_balance( + key_name="alice", contract_name=contract_name + ).balance + assert alice_balance == TX_AMOUNT + + @pytest.mark.parametrize( + "transaction_file,use_json", + [ + ("sapling_transaction.bin", False), + ("sapling_transaction.json", True), + ], + ) + def test_forge_alice_to_bob_insufficient_funds( + self, client, tmpdir, contract_name, session, transaction_file, use_json + ): + transaction_file = f'{tmpdir}/{transaction_file}' + amount = 2100000000.0 + account = 'alice' + additional_args = [] + if use_json: + additional_args += ["--json"] + + with assert_run_failure( + r"Balance too low \({}\) to spend {}".format(100, int(amount)) + ): + client.sapling_forge_transaction( + amount=amount, + src=account, + dest=session['bob_address_1'], + contract=contract_name, + file=transaction_file, + args=additional_args, + ) + + def test_forge_alice_to_bob_address_0( + self, tmpdir, session, client, contract_name + ): + transaction_file = f'{tmpdir}/sapling_transaction0.bin' + client.sapling_forge_transaction( + amount=TX_AMOUNT, + src='alice', + dest=session['bob_address_0'], + contract=contract_name, + file=transaction_file, + ) + + def test_forge_alice_to_bob_address_1_binary_format( + self, tmpdir, session, client, contract_name + ): + transaction_file = f'{tmpdir}/sapling_transaction1.bin' + client.sapling_forge_transaction( + amount=50.0, + src='alice', + dest=session['bob_address_1'], + contract=contract_name, + file=transaction_file, + ) + + @pytest.mark.parametrize( + "key_name,expected_balance", [("alice", TX_AMOUNT), ("bob", TX_AMOUNT)] + ) + def test_check_sapling_balances_post_forge_binary_format( + self, client, contract_name, key_name, expected_balance + ): + result = client.sapling_get_balance( + key_name=key_name, + contract_name=contract_name, + ) + assert result.balance == expected_balance + + def test_submit_alice_to_bob_address_1_binary_format( + self, client, tmpdir, contract_name + ): + transaction_file = f'{tmpdir}/sapling_transaction1.bin' + additional_args = ["--burn-cap", "3.0"] + client.sapling_submit( + file=transaction_file, + fee_payer='bootstrap2', + contract=contract_name, + args=additional_args, + ) + client.bake("bootstrap2", ["--minimal-timestamp"]) + + @pytest.mark.parametrize( + "key_name,expected_balance", [("alice", 50.0), ("bob", 150.0)] + ) + def test_check_sapling_balances_after_successfull_transaction_in_binary( + self, client, contract_name, key_name, expected_balance + ): + balance = client.sapling_get_balance( + key_name=key_name, contract_name=contract_name + ).balance + assert balance == expected_balance + + def test_forge_alice_to_bob_address_1_json_format( + self, tmpdir, session, client, contract_name + ): + transaction_file = f'{tmpdir}/sapling_transaction1.json' + client.sapling_forge_transaction( + amount=50.0, + src='alice', + dest=session['bob_address_1'], + contract=contract_name, + file=transaction_file, + args=['--json'], + ) + # Try to load the file as JSON. Must not fail. + with open(transaction_file, "r") as file_descriptor: + json.load(file_descriptor) + + @pytest.mark.parametrize( + "key_name,expected_balance", [("alice", 50.0), ("bob", 150.0)] + ) + def test_check_sapling_balances_post_forge_json_format( + self, client, contract_name, key_name, expected_balance + ): + result = client.sapling_get_balance( + key_name=key_name, + contract_name=contract_name, + ) + assert result.balance == expected_balance + + def test_submit_alice_to_bob_address_1_json_format( + self, client, tmpdir, contract_name + ): + transaction_file = f'{tmpdir}/sapling_transaction1.json' + additional_args = ["--burn-cap", "3.0", "--json"] + client.sapling_submit( + file=transaction_file, + fee_payer='bootstrap2', + contract=contract_name, + args=additional_args, + ) + client.bake("bootstrap2", ["--minimal-timestamp"]) + + @pytest.mark.parametrize( + "key_name,expected_balance", [("alice", 0.0), ("bob", 200.0)] + ) + def test_check_sapling_balances_after_successfull_transaction_in_json( + self, client, contract_name, key_name, expected_balance + ): + balance = client.sapling_get_balance( + key_name=key_name, contract_name=contract_name + ).balance + assert balance == expected_balance + + @pytest.mark.parametrize( + "transaction_file,use_json", + [ + ("sapling_transaction0.bin", False), + # ("sapling_transaction0.json", True), + ], + ) + def test_submit_alice_to_bob0( + self, client, transaction_file, use_json, tmpdir, contract_name + ): + transaction_file = f'{tmpdir}/{transaction_file}' + additional_args = ["--burn-cap", "3.0"] + if use_json: + additional_args.append("--json") + + with assert_run_failure(r'transfer simulation failed'): + client.sapling_submit( + file=transaction_file, + fee_payer='bootstrap2', + contract=contract_name, + args=additional_args, + ) + + @pytest.mark.parametrize( + "requested_token,real_balance,key_name", + [ + (2100000000, 200, "bob"), + (300, 200, "bob"), + (2100000000, 0, "alice"), + (100, 0, "alice"), + ], + ) + def test_unshields_money_insufficient_funds( + self, client, contract_name, requested_token, real_balance, key_name + ): + with assert_run_failure( + r'Balance too low \({}\) to spend {}'.format( + real_balance, requested_token + ) + ): + client.sapling_unshield( + amount=requested_token, + src=key_name, + dest="bootstrap4", + contract=contract_name, + args=["--burn-cap", "3.0"], + ) + + def test_bob_unshields_money(self, client, contract_name): + bootstrap4_prev_balance = client.get_balance('bootstrap4') + amount = 90.0 + client.sapling_unshield( + amount=amount, + src="bob", + dest="bootstrap4", + contract=contract_name, + args=["--burn-cap", "3.0"], + ) + client.bake("bootstrap2", ['--minimal-timestamp']) + bob_balance = client.sapling_get_balance( + key_name="bob", contract_name=contract_name + ).balance + assert bob_balance == 200.0 - amount + bootstrap4_balance = client.get_balance("bootstrap4") + # The receiver pays fees by default so it will not get the full amount, + # but still, it should have more than before + assert bootstrap4_balance >= bootstrap4_prev_balance + assert bootstrap4_balance <= bootstrap4_prev_balance + amount + + def test_check_state_with_another_client( + self, sandbox, node, contract_name, session + ): + client = sandbox.get_new_client(node) + client.remember_contract(contract_name, session["contract_address"]) + key_name = "bob" + # Restore bob's key from mnemonic: + client.sapling_import_key( + key_name=key_name, + mnemonic=session['bob_mnemonic'], + ) + client.sapling_use_key_for_contract( + key_name, contract_name, memo_size=8 + ) + # Check Bob's balance again, it should be the same: + bob_balance = client.sapling_get_balance( + key_name=key_name, contract_name=contract_name + ).balance + assert bob_balance == 110.0 + + @pytest.mark.parametrize( + "transparent_signer,baker", [("bootstrap4", "bootstrap2")] + ) + def test_shielded_transfer_using_non_sapling_transfer_method( + self, client, contract_name, session, transparent_signer, baker, tmpdir + ): + transaction_filename = f'{tmpdir}/sapling_transaction_2.bin' + client.sapling_forge_transaction( + amount=10.0, + src='bob', + dest=session['bob_address_1'], + contract=contract_name, + file=transaction_filename, + args=[], + ) + with open(transaction_filename, "r") as file_descriptor: + content = re.sub(r'\s+', ' ', file_descriptor.read()) + client.transfer( + 0, + giver=transparent_signer, + receiver=contract_name, + args=[ + "--arg", + '{Pair %s None }' % content, + "--burn-cap", + "3.0", + ], + ) + client.bake(baker, ["--minimal-timestamp"]) + + @pytest.mark.parametrize( + "key_name,expected_balance", [("alice", 0.0), ("bob", 110.0)] + ) + def test_check_sapling_balances_after_calling_smart_contract( + self, client, contract_name, key_name, expected_balance + ): + balance = client.sapling_get_balance( + key_name=key_name, contract_name=contract_name + ).balance + assert balance == expected_balance + + +class TestSaplingMemoSize: + @pytest.fixture(scope="class") + def contract_name(self): + return "sapling_memo_size" + + @pytest.fixture(scope="class") + def contract_generator(self): + def generator(memo_size): + return ''' +parameter unit; +storage (sapling_state %s); +code { + DROP; + SAPLING_EMPTY_STATE %s; + NIL operation; + PAIR; + } +''' % ( + memo_size, + memo_size, + ) + + return generator + + @pytest.mark.parametrize("memo_size", [0, 1, 10, 42, 100, 65535]) + def test_originate_with_valid_size_and_update_with_valid_size( + self, client, memo_size, contract_name, tmpdir, contract_generator + ): + contract_path = tmpdir.join("c.tz") + contract_path.write(contract_generator(memo_size)) + sender = "bootstrap1" + client.originate( + contract_name=contract_name, + amount=0, + sender=sender, + contract=str(contract_path), + args=["--init", '{ }', "--burn-cap", "3.0", "--force"], + ) + client.bake("bootstrap1", ["--minimal-timestamp"]) + client.transfer( + 0, + giver="bootstrap1", + receiver=contract_name, + args=["--arg", "Unit", "--burn-cap", "3.0"], + ) + client.bake("bootstrap1", ["--minimal-timestamp"]) + + @pytest.mark.parametrize("memo_size", [-1, 65536, 65598909, 908923434]) + def test_originate_with_invalid_size( + self, + client, + memo_size, + contract_path, + contract_name, + contract_generator, + tmpdir, + ): + contract_path = tmpdir.join("c.tz") + contract_path.write(contract_generator(memo_size)) + sender = "bootstrap1" + err = r"expected a positive 16-bit integer" + with assert_run_failure(err): + client.originate( + contract_name=contract_name, + amount=0, + sender=sender, + contract=str(contract_path), + args=["--init", "{ }", "--burn-cap", "3.0", "--force"], + ) + + +@pytest.mark.incremental +class TestSaplingStateCorruption: + @pytest.fixture(scope="session") + def tmpdir(self, tmpdir_factory): + """ + Temporary directory. Forged transactions will be saved + in this directory. + FIXME/IMPROVEME: tmpdir_factory is a fixture provided by pytest. It is + session-scoped, then the fixture tmpdir must be session-scoped. + Would be nice to have a class-scoped fixture. + """ + tmpdir = tmpdir_factory.mktemp("sapling_transactions_shielded_tez") + return tmpdir + + def test_push_sapling_state_with_id_is_forbidden( + self, client, contract_path + ): + contract_name = ( + f"{contract_path}/contracts/sapling_push_sapling_state.tz" + ) + sender = "bootstrap1" + msg = r"big_map or sapling_state type not expected here" + with assert_run_failure(msg): + client.originate( + contract_name="push_sapling_state", + amount=0, + sender=sender, + contract=contract_name, + args=["--init", "Unit", "--burn-cap", "3.0"], + ) + + def test_originate_with_empty(self, client): + """ + Makes sure sapling state with id 0 exists + """ + contract = path.join( + contract_paths.OPCODES_CONTRACT_PATH, "sapling_empty_state.tz" + ) + client.originate( + amount=0, + sender="bootstrap1", + contract=contract, + contract_name="sapling_empty_state", + args=["--init", "{}", "--burn-cap", "3.0"], + ) + client.bake("bootstrap1") + + def test_originate_with_id_is_forbidden(self, client): + contract = path.join( + contract_paths.OPCODES_CONTRACT_PATH, "sapling_empty_state.tz" + ) + with assert_run_failure(r'Unexpected forged value'): + client.originate( + amount=0, + sender="bootstrap1", + contract=contract, + contract_name="sapling_empty_state2", + args=["--init", "0", "--burn-cap", "3.0"], + ) + + +class TestSaplingDifferentMemosize: + """ + Deploy a sapling contract using a sapling state with a memo size N and + create transactions with a memo size of M + """ + + @pytest.fixture + def contract_path(self): + return ( + f'{paths.TEZOS_HOME}/src/proto_009_PsFLoren/lib_protocol/test/' + 'contracts/sapling_contract.tz' + ) + + def test_shield_with_different_memo_size(self, contract_path, client): + contract_name = "sapling_memo_size_different" + implicit_account = "bootstrap1" + contract_address = client.originate( + contract_name=contract_name, + amount=0, + sender=implicit_account, + contract=contract_path, + args=["--init", "{ }", "--burn-cap", "3.0"], + ).contract + client.bake(implicit_account, ["--minimal-timestamp"]) + client.sapling_gen_key(key_name='alice') + client.sapling_use_key_for_contract( + 'alice', contract_name, memo_size=16 + ) + address = client.sapling_gen_address(key_name='alice').address + # Key was registered with a memo_size of 16, it should fail + with assert_run_failure(r"Memo sizes of two sapling states"): + client.sapling_shield( + amount=TX_AMOUNT, + src=implicit_account, + dest=address, + contract=contract_address, + args=["--burn-cap", "3.0"], + ) + + +class TestSaplingRightMemosize: + """ + Deploy a sapling contract using a sapling state with a memo size N and + create transactions with a memo size of N and diverse messages + """ + + @pytest.fixture + def contract_path(self): + return ( + f'{paths.TEZOS_HOME}/src/proto_009_PsFLoren/lib_protocol/test/' + 'contracts/sapling_contract.tz' + ) + + def test_shield_with_same_memo_size(self, contract_path, client): + contract_name = "sapling_memo_size_same" + implicit_account = "bootstrap1" + contract_address = client.originate( + contract_name=contract_name, + amount=0, + sender=implicit_account, + contract=contract_path, + args=["--init", "{ }", "--burn-cap", "3.0"], + ).contract + client.bake(implicit_account, ["--minimal-timestamp"]) + client.sapling_gen_key(key_name='alice') + client.sapling_use_key_for_contract('alice', contract_name, memo_size=8) + address = client.sapling_gen_address(key_name='alice').address + # Should pass since memo-sizes are equal and message is + # filled with 0's + client.sapling_shield( + amount=TX_AMOUNT, + src=implicit_account, + dest=address, + contract=contract_address, + args=["--burn-cap", "3.0"], + ) + client.bake("bootstrap2", ["--minimal-timestamp"]) + # Deriving a new key should work as well since + # the memo-size is kept + client.sapling_derive_key( + source_key_name='alice', + target_key_name='bob', + contract_name=contract_name, + index=10, + ) + address_derived = client.sapling_gen_address(key_name='bob').address + client.sapling_shield( + amount=TX_AMOUNT, + src=implicit_account, + dest=address_derived, + contract=contract_address, + args=["--burn-cap", "3.0"], + ) + client.bake("bootstrap2", ["--minimal-timestamp"]) + # Now with a too short message + client.sapling_shield( + amount=TX_AMOUNT, + src=implicit_account, + dest=address, + contract=contract_address, + args=["--burn-cap", "3.0", "--message", "aB"], + ) + client.bake("bootstrap2", ["--minimal-timestamp"]) + # Now with a right length message + client.sapling_shield( + amount=TX_AMOUNT, + src=implicit_account, + dest=address, + contract=contract_address, + args=["--burn-cap", "3.0", "--message", "aBbf19F00a"], + ) + client.bake("bootstrap2", ["--minimal-timestamp"]) + # Now with a too long message + client.sapling_shield( + amount=TX_AMOUNT, + src=implicit_account, + dest=address, + contract=contract_address, + args=["--burn-cap", "3.0", "--message", "aBbf19F00aaBbf19F00aC"], + ) + client.bake("bootstrap2", ["--minimal-timestamp"]) diff --git a/tests_python/tests_009/test_slice_fails_params.txt b/tests_python/tests_009/test_slice_fails_params.txt new file mode 100644 index 0000000000000000000000000000000000000000..7241bd22aff35f4c48ef00a059b8a0968f78556b --- /dev/null +++ b/tests_python/tests_009/test_slice_fails_params.txt @@ -0,0 +1,5 @@ +(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "p2sigsceCzcDw2AeYDzUonj4JT341WC9Px4wdhHBxbZcG1FhfqFVuG7f2fGCzrEHSAZgrsrQWpxduDPk9qZRgrpzwJnSHC3gZJ") +(Pair 0xeaa9ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") +(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2deaad01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") +(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150733eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") +(Pair 0xe009ab79e8b84ef0 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") diff --git a/tests_python/tests_009/test_slice_success_params.txt b/tests_python/tests_009/test_slice_success_params.txt new file mode 100644 index 0000000000000000000000000000000000000000..8c0d89bd81420ef39e1218e19b6475b23ff46444 --- /dev/null +++ b/tests_python/tests_009/test_slice_success_params.txt @@ -0,0 +1 @@ +(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") diff --git a/tests_python/tests_009/test_tls.py b/tests_python/tests_009/test_tls.py new file mode 100755 index 0000000000000000000000000000000000000000..e09a585722c352a018eeb3f92b1a8f41935d078f --- /dev/null +++ b/tests_python/tests_009/test_tls.py @@ -0,0 +1,22 @@ +import pytest +from tools import constants +from client.client import Client + + +@pytest.fixture(scope="class") +def client(sandbox): + sandbox.add_node( + 0, + use_tls=(constants.TEZOS_CRT, constants.TEZOS_KEY), + params=constants.NODE_PARAMS, + ) + yield sandbox.client(0) + + +@pytest.mark.vote +@pytest.mark.incremental +class TestTLS: + """Test voting protocol with manual baking, 4 blocks per voting period.""" + + def test_bootstrapped(self, client: Client): + assert client.bootstrapped() diff --git a/tests_python/tests_009/test_voting.py b/tests_python/tests_009/test_voting.py new file mode 100644 index 0000000000000000000000000000000000000000..7bcab2e29ef747f04d5aac5b70e51a7c97cdac8f --- /dev/null +++ b/tests_python/tests_009/test_voting.py @@ -0,0 +1,299 @@ +import shutil + +import pytest + +from client.client import Client +from tools import constants, paths + +from . import protocol + +BAKE_ARGS = [ + '--minimal-fees', + '0', + '--minimal-nanotez-per-byte', + '0', + '--minimal-nanotez-per-gas-unit', + '0', + '--max-priority', + '512', + '--minimal-timestamp', +] + + +@pytest.fixture(scope="class") +def client(sandbox): + """One node, 4 blocks per voting period.""" + parameters = dict(protocol.PARAMETERS) + parameters["time_between_blocks"] = ["1", "0"] + parameters["blocks_per_voting_period"] = 4 + sandbox.add_node(0, params=constants.NODE_PARAMS) + protocol.activate(sandbox.client(0), parameters, activate_in_the_past=True) + yield sandbox.client(0) + + +@pytest.mark.vote +@pytest.mark.incremental +class TestManualBaking: + """Test voting protocol with manual baking, 4 blocks per voting period.""" + + def test_current_period(self, client: Client): + period_info = client.get_current_period() + level = client.get_current_level() + assert level["level_position"] == 0 + assert period_info["voting_period"]["index"] == 0 + assert period_info["voting_period"]["kind"] == "proposal" + assert period_info["voting_period"]["start_position"] == 0 + assert period_info["position"] == 0 + assert period_info["remaining"] == 3 + + def test_succ_period(self, client: Client): + period_info = client.get_succ_period() + assert period_info["voting_period"]["index"] == 0 + assert period_info["voting_period"]["kind"] == "proposal" + assert period_info["voting_period"]["start_position"] == 0 + assert period_info["position"] == 1 + assert period_info["remaining"] == 2 + + def test_level_info_period_offset(self, client: Client): + level = client.get_current_level(offset=1) + assert level["level_position"] == 1 + assert level["voting_period"] == 0 + assert level["voting_period_position"] == 1 + level = client.get_current_level(offset=4) + assert level["level_position"] == 4 + assert level["voting_period"] == 1 + assert level["voting_period_position"] == 0 + level = client.get_current_level(offset=10) + assert level["level_position"] == 10 + assert level["voting_period"] == 2 + assert level["voting_period_position"] == 2 + + def test_bake_two_blocks(self, client: Client): + client.bake('bootstrap1', BAKE_ARGS) + client.bake('bootstrap1', BAKE_ARGS) + period_info = client.get_current_period() + level = client.get_current_level() + assert level["level_position"] == 2 + assert period_info["voting_period"]["index"] == 0 + assert period_info["voting_period"]["kind"] == "proposal" + assert period_info["voting_period"]["start_position"] == 0 + assert period_info["position"] == 2 + assert period_info["remaining"] == 1 + + def test_last_block_of_proposal_period(self, client: Client): + # last block of voting period 0 + client.bake('bootstrap1', BAKE_ARGS) + period_info = client.get_current_period() + assert period_info["voting_period"]["index"] == 0 + assert period_info["voting_period"]["kind"] == "proposal" + assert period_info["voting_period"]["start_position"] == 0 + assert period_info["position"] == 3 + assert period_info["remaining"] == 0 + + def test_listing_is_not_empty(self, client: Client): + assert client.get_listings() != [] + + def test_inject_proto1(self, client: Client, tmpdir): + proto_fp = ( + f'{paths.TEZOS_HOME}/src/' f'bin_client/test/proto_test_injection' + ) + for i in range(1, 4): + proto = f'{tmpdir}/proto{i}' + shutil.copytree(proto_fp, proto) + main = f'{proto}/main.ml' + print(main) + with open(main, "a") as file: + file.write(f'(* {i} *)') + client.inject_protocol(proto) + + # this is maybe useless because the protocol already knows more than 4 + # protocol + def test_known_protocol(self, client: Client, session: dict): + protos = client.list_protocols() + assert len(protos) >= 4 + session['protos'] = protos[:4] + + def test_proposals_is_empty(self, client: Client): + assert client.get_proposals() == [] + + def test_show_voting_period2(self, client: Client): + client.show_voting_period() + + def test_bake_first_block_of_proposal_period(self, client: Client): + # using the client it's not possible to add voting operation on the + # first block of a voting period. This is to be fixed in a futur + # protocol + client.bake('bootstrap1', BAKE_ARGS) + period_info = client.get_current_period() + assert period_info["voting_period"]["index"] == 1 + assert period_info["voting_period"]["kind"] == "proposal" + assert period_info["voting_period"]["start_position"] == 4 + assert period_info["position"] == 0 + assert period_info["remaining"] == 3 + + def test_submit_proposals(self, client: Client, session: dict): + protos = session['protos'] + client.submit_proposals('bootstrap1', [protos[0]]) + client.submit_proposals('bootstrap2', [protos[0], protos[1]]) + client.submit_proposals('bootstrap3', [protos[1]]) + client.submit_proposals('bootstrap4', [protos[2]]) + + def test_bake_one_block(self, client: Client): + client.bake('bootstrap1', BAKE_ARGS) + period_info = client.get_current_period() + assert period_info["voting_period"]["index"] == 1 + assert period_info["voting_period"]["kind"] == "proposal" + assert period_info["voting_period"]["start_position"] == 4 + assert period_info["position"] == 1 + assert period_info["remaining"] == 2 + + def test_proposals_is_not_empty(self, client: Client): + assert client.get_proposals() != [] + + def test_bake_until_prev_last_block_of_voting_period(self, client: Client): + client.bake('bootstrap1', BAKE_ARGS) + period_info = client.get_current_period() + assert period_info["position"] == 2 + assert period_info["remaining"] == 1 + + def test_break_proposal_tie(self, client: Client, session: dict): + protos = session['protos'] + client.submit_proposals('bootstrap4', [protos[1]]) + + def test_bake_last_block_of_proposal_period(self, client: Client): + client.bake('bootstrap1', BAKE_ARGS) + period_info = client.get_current_period() + metadata = client.get_metadata() + meta_level = metadata["level"] + level_info = metadata["level_info"] + meta_period_info = metadata["voting_period_info"] + expected_commitment = meta_level["expected_commitment"] + deprecated_period_kind = metadata["voting_period_kind"] + period_index = metadata["level"]["voting_period"] + period_position = metadata["level"]["voting_period_position"] + level = client.get_current_level() + # check if metadata has the same value as the level and voting period, + # see inline comment in alpha apply.ml. This is tested here because the + # level of metadata and current level use the compatibility encoding + # that contains the voting period information + assert meta_level == level + assert level["level"] == level_info["level"] + assert level["level_position"] == level_info["level_position"] + assert level["cycle"] == level_info["cycle"] + assert level["cycle_position"] == level_info["cycle_position"] + assert expected_commitment == level_info["expected_commitment"] + assert period_index == period_info["voting_period"]["index"] + assert deprecated_period_kind == "exploration" + assert period_position == period_info["position"] + assert level["level_position"] == 7 + assert period_info["voting_period"]["index"] == 1 + assert period_info["voting_period"]["kind"] == "proposal" + assert period_info["voting_period"]["start_position"] == 4 + assert period_info["position"] == 3 + assert period_info["remaining"] == 0 + assert meta_period_info == period_info + + def test_listing_is_not_empty2(self, client: Client): + assert client.get_listings() != [] + + def test_current_proposal(self, client: Client, session: dict): + expected = session['protos'][1] + assert expected == client.get_current_proposal() + + def test_bake_first_block_of_cooldown_vote_period(self, client: Client): + # using the client it's not possible to add voting operation on the + # first block of a voting period. This is to be fixed in a futur + # protocol + client.bake('bootstrap1', BAKE_ARGS) + period_info = client.get_current_period() + assert period_info["voting_period"]["index"] == 2 + assert period_info["voting_period"]["kind"] == "exploration" + assert period_info["voting_period"]["start_position"] == 8 + assert period_info["position"] == 0 + assert period_info["remaining"] == 3 + + def test_submit_ballot(self, client: Client, session: dict): + # next block is going to be of 'exploration' kind + proto = session['protos'][1] + for i in range(1, 4): + client.submit_ballot(f'bootstrap{i}', proto, 'yay') + + def test_bake_until_prev_last_block_of_voting_period2(self, client: Client): + client.bake('bootstrap1', BAKE_ARGS) + client.bake('bootstrap1', BAKE_ARGS) + period_info = client.get_current_period() + level = client.get_current_level() + assert level["level_position"] == 10 + assert period_info["voting_period"]["index"] == 2 + assert period_info["voting_period"]["kind"] == "exploration" + assert period_info["voting_period"]["start_position"] == 8 + assert period_info["position"] == 2 + assert period_info["remaining"] == 1 + + def test_submit_failing_ballot(self, client: Client, session: dict): + proto = session['protos'][1] + client.submit_ballot(f'bootstrap{4}', proto, 'nay') + + def test_level_info_period_offset2(self, client: Client): + level = client.get_current_level(offset=-1) + assert level["level_position"] == 9 + assert level["voting_period"] == 2 + assert level["voting_period_position"] == 1 + level = client.get_current_level(offset=-4) + assert level["level_position"] == 6 + assert level["voting_period"] == 1 + assert level["voting_period_position"] == 2 + level = client.get_current_level(offset=-10) + assert level["level_position"] == 0 + assert level["voting_period"] == 0 + assert level["voting_period_position"] == 0 + + def test_bake_first_block_of_new_proposal_period(self, client: Client): + client.bake('bootstrap1', BAKE_ARGS) + # Because of the current hack in proposal here we make sure we get the + # correct value + period_info = client.get_current_period() + metadata = client.get_metadata() + meta_level = metadata["level"] + level_info = metadata["level_info"] + meta_period_info = metadata["voting_period_info"] + expected_commitment = meta_level["expected_commitment"] + period_kind = metadata["voting_period_kind"] + period_index = metadata["level"]["voting_period"] + period_position = metadata["level"]["voting_period_position"] + level = client.get_current_level() + deprecated_kind = client.get_current_period_kind() + # check if metadata has the same value as the level and voting period, + # see inline comment in alpha apply.ml. This is tested here because the + # level of metadata and current level use the compatibility encoding + # that contains the voting period information + assert meta_level == level + assert level["level"] == level_info["level"] + assert level["level_position"] == level_info["level_position"] + assert level["cycle"] == level_info["cycle"] + assert level["cycle_position"] == level_info["cycle_position"] + assert expected_commitment == level_info["expected_commitment"] + assert period_index == period_info["voting_period"]["index"] + assert period_kind == "proposal" + assert period_kind == deprecated_kind + assert period_position == period_info["position"] + assert level["level_position"] == 11 + assert period_info["voting_period"]["index"] == 2 + assert period_info["voting_period"]["kind"] == "exploration" + assert period_info["voting_period"]["start_position"] == 8 + assert period_info["position"] == 3 + assert period_info["remaining"] == 0 + assert meta_period_info == period_info + client.bake('bootstrap1', BAKE_ARGS) + period_info = client.get_current_period() + level = client.get_current_level() + assert level["level_position"] == 12 + assert period_info["voting_period"]["index"] == 3 + assert period_info["voting_period"]["kind"] == "proposal" + assert period_info["voting_period"]["start_position"] == 12 + assert period_info["position"] == 0 + assert period_info["remaining"] == 3 + assert client.get_listings() != '[]' + # strange behavior here, RPC returns 'null' on stderr + assert client.get_current_proposal() is None + assert client.get_ballot_list() == [] diff --git a/tests_python/tests_009/test_voting_full.py b/tests_python/tests_009/test_voting_full.py new file mode 100644 index 0000000000000000000000000000000000000000..fff8707c4a5c46667548f772307657eecb0eaec3 --- /dev/null +++ b/tests_python/tests_009/test_voting_full.py @@ -0,0 +1,176 @@ +import time + +import pytest + +from launchers.sandbox import Sandbox +from client.client import Client +from tools import utils, constants +from . import protocol + +BLOCKS_PER_VOTING_PERIOD = 8 +OFFSET = int(BLOCKS_PER_VOTING_PERIOD / 2) +POLLING_TIME = 5 +NUM_NODES = 3 +BAKER = "bootstrap1" +BAKE_ARGS = ['--minimal-timestamp'] +ERROR_PATTERN = r"Uncaught|registered|error" + +PROTO_A = protocol.PREV_HASH +PROTO_A_DAEMON = protocol.PREV_DAEMON +PROTO_A_PATH = f"proto_{PROTO_A_DAEMON.replace('-','_')}" +PROTO_B = protocol.HASH +PROTO_B_DAEMON = protocol.DAEMON + + +def client_get_current_period_kind(client) -> dict: + res = client.get_current_period() + return res['voting_period']['kind'] + + +def bake_n_blocks(client: Client, baker: str, n_blocks: int): + for _ in range(n_blocks): + client.bake(baker, BAKE_ARGS) + + +def bake_until_next_voting_period(client: Client, baker: str, offset: int = 0): + period_info = client.get_current_period() + remaining_blocks = period_info["remaining"] + # if offset is the constant OFFSET, it will take us to + # the middle of the next voting period + bake_n_blocks(client, baker, 1 + remaining_blocks + offset) + + +@pytest.mark.timeout(10) +def wait_until_level(clients, level): + for client in clients: + while client.get_level() < level: + time.sleep(1) + + +def assert_all_clients_in_period(clients, period): + for client in clients: + assert client_get_current_period_kind(client) == period + + +@pytest.mark.vote +@pytest.mark.slow +@pytest.mark.baker +@pytest.mark.incremental +class TestVotingFull: + """This tests the migration from PROTO_A to PROTO_B using the voting + procedure. PROTO_A and PROTO_B are the previous and + respectively the current protocol as given by the 'protocol' + module. + + This test advances through all the periods of the voting procedure + until the last one (adoption), by manually baking the right number + of blocks. Once the adoption period is reached, a baker takes over + to bake the remaining blocks of the period. From there the baker + for the next protocol, which was started at the beginning of the + test, takes over. (Bakers are used to make the test more + realistic. However, to be sure that proposals and ballots are + injected at the right moment, manual baking is used instead.) + + This test differs in the following aspects from test_voting.py: + - it uses more nodes, not just one + - it goes through all voting periods, not just the first two + - it uses bakers + - it uses already registered protocols, instead of injecting a + new dummy protocol + """ + + def test_add_initial_nodes(self, sandbox: Sandbox): + for i in range(NUM_NODES): + sandbox.add_node(i, params=constants.NODE_PARAMS) + parameters = dict(protocol.PREV_PARAMETERS) + parameters["blocks_per_voting_period"] = BLOCKS_PER_VOTING_PERIOD + utils.activate_protocol( + sandbox.client(0), PROTO_A, parameters, activate_in_the_past=True + ) + + def test_add_baker(self, sandbox: Sandbox): + sandbox.add_baker(0, BAKER, proto=PROTO_B_DAEMON) + + def test_client_knows_proto_b(self, sandbox: Sandbox): + client = sandbox.client(0) + protos = client.list_protocols() + assert PROTO_B in protos + + def test_proposal_period(self, sandbox: Sandbox): + assert_all_clients_in_period(sandbox.all_clients(), 'proposal') + + def test_submit_proto_b_proposal(self, sandbox): + client = sandbox.client(0) + proposals = client.submit_proposals(BAKER, [PROTO_B]) + # bake a block for the submit proposal to be included + bake_n_blocks(client, BAKER, 1) + client.wait_for_inclusion(proposals.operation_hash, check_previous=1) + + def test_check_proto_b_proposed(self, sandbox: Sandbox): + clients = sandbox.all_clients() + wait_until_level(clients, sandbox.client(0).get_level()) + for client in clients: + proposals = client.get_proposals() + assert PROTO_B in [proto for (proto, _) in proposals] + + def test_wait_for_testing_vote_period(self, sandbox: Sandbox): + client = sandbox.client(0) + bake_until_next_voting_period(client, BAKER, OFFSET) + clients = sandbox.all_clients() + wait_until_level(clients, client.get_level()) + assert_all_clients_in_period(clients, 'testing_vote') + + def test_delegates_vote_proto_b(self, sandbox: Sandbox): + client = sandbox.client(0) + listings = client.get_listings() + # submit ballot for all bakers with listings + for listing in listings: + client.submit_ballot(listing["pkh"], PROTO_B, 'yay') + + def test_wait_for_cooldown(self, sandbox: Sandbox): + client = sandbox.client(0) + bake_until_next_voting_period(client, BAKER, OFFSET) + clients = sandbox.all_clients() + wait_until_level(clients, client.get_level()) + assert_all_clients_in_period(clients, 'testing') + + def test_wait_for_promotion_vote_period(self, sandbox: Sandbox): + client = sandbox.client(0) + bake_until_next_voting_period(client, BAKER, OFFSET) + clients = sandbox.all_clients() + wait_until_level(clients, client.get_level()) + assert_all_clients_in_period(clients, 'promotion_vote') + + def test_vote_in_promotion_phase(self, sandbox: Sandbox): + client = sandbox.client(0) + listings = client.get_listings() + for listing in listings: + client.submit_ballot(listing["pkh"], PROTO_B, 'yay') + + def test_wait_for_adoption(self, sandbox: Sandbox): + client = sandbox.client(0) + bake_until_next_voting_period(client, BAKER) + clients = sandbox.all_clients() + wait_until_level(clients, client.get_level()) + assert_all_clients_in_period(clients, 'adoption') + + @pytest.mark.timeout(60) + def test_all_nodes_run_proto_b(self, sandbox: Sandbox): + # we let a PROTO_A baker bake the last blocks of PROTO_A + sandbox.add_baker(0, BAKER, proto=PROTO_A_DAEMON) + clients = sandbox.all_clients() + all_have_proto = False + while not all_have_proto: + all_have_proto = all( + client.get_protocol() == PROTO_B for client in clients + ) + time.sleep(POLLING_TIME) + + def test_new_chain_progress(self, sandbox: Sandbox): + client = sandbox.client(0) + level_before = client.get_level() + assert utils.check_level_greater_than(client, level_before + 1) + + @pytest.mark.xfail + def test_check_logs(self, sandbox: Sandbox): + assert utils.check_logs(sandbox.logs, ERROR_PATTERN) diff --git a/tests_python/tools/constants.py b/tests_python/tools/constants.py index ada0634dad8a0d10d9df26df4e08bd619c423b94..3765dcd9836edbb3ceb1a718980dbae6f8a98bbb 100644 --- a/tests_python/tools/constants.py +++ b/tests_python/tools/constants.py @@ -93,6 +93,10 @@ EDO = "PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA" EDO_DAEMON = "008-PtEdo2Zk" EDO_PARAMETERS = get_parameters("008_PtEdo2Zk") +FLORENCE = "PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i" +FLORENCE_DAEMON = "009-PsFLoren" +FLORENCE_PARAMETERS = get_parameters("009_PsFLoren") + TEZOS_CRT = """ Certificate: Data: diff --git a/vendors/flextesa-lib/tezos_protocol.ml b/vendors/flextesa-lib/tezos_protocol.ml index 2e0d06a67b51e95861fd9209c84965eba5785a68..0e6195327b5f41a95788cdc2004564455ada03ef 100644 --- a/vendors/flextesa-lib/tezos_protocol.ml +++ b/vendors/flextesa-lib/tezos_protocol.ml @@ -74,11 +74,11 @@ module Voting_period = struct end module Protocol_kind = struct - type t = [`Athens | `Babylon | `Carthage | `Delphi | `Edo | `Alpha] + type t = [`Athens | `Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha] let names = [ ("Athens", `Athens); ("Babylon", `Babylon); ("Carthage", `Carthage) - ; ("Delphi", `Delphi); ("Edo", `Edo); ("Alpha", `Alpha) ] + ; ("Delphi", `Delphi); ("Edo", `Edo); ("Florence", `Florence); ("Alpha", `Alpha) ] let default = `Alpha @@ -154,7 +154,7 @@ let protocol_parameters_json t : Ezjsonm.t = match subkind with | `Babylon -> (800_000, 8_000_000) | `Carthage -> (1_040_000, 10_400_000) - | `Delphi | `Edo | `Alpha -> (1_040_000, 10_400_000) in + | `Delphi | `Edo | `Florence | `Alpha -> (1_040_000, 10_400_000) in let open Ezjsonm in let list_of_zs = list (fun i -> string (Int.to_string i)) in [ ("blocks_per_commitment", int 4); ("endorsers_per_block", int 32) @@ -168,18 +168,18 @@ let protocol_parameters_json t : Ezjsonm.t = ; ("endorsement_security_deposit", string (Int.to_string 64_000_000)) ; ( match subkind with | `Babylon -> ("block_reward", string (Int.to_string 16_000_000)) - | `Carthage | `Delphi | `Edo | `Alpha -> + | `Carthage | `Delphi | `Edo | `Florence | `Alpha -> ( "baking_reward_per_endorsement" , list_of_zs t.baking_reward_per_endorsement ) ) ; ( "endorsement_reward" , match subkind with | `Babylon -> string (Int.to_string 2_000_000) - | `Carthage | `Delphi | `Edo | `Alpha -> list_of_zs t.endorsement_reward + | `Carthage | `Delphi | `Edo | `Florence | `Alpha -> list_of_zs t.endorsement_reward ); ("hard_storage_limit_per_operation", string (Int.to_string 60_000)) ; ( "cost_per_byte" , match subkind with | `Babylon | `Carthage -> string (Int.to_string 1_000) - | `Delphi | `Edo | `Alpha -> string (Int.to_string 250) ) + | `Delphi | `Edo | `Florence | `Alpha -> string (Int.to_string 250) ) ; ("test_chain_duration", string (Int.to_string 1_966_080)) ; ("quorum_min", int 3_000); ("quorum_max", int 7_000) ; ("min_proposal_quorum", int 500); ("initial_endorsers", int 1) @@ -201,7 +201,7 @@ let protocol_parameters_json t : Ezjsonm.t = | None -> dict ( match t.kind with - | (`Babylon | `Carthage | `Delphi | `Edo | `Alpha) as sk -> + | (`Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha) as sk -> common @ extra_post_babylon_stuff sk | `Athens -> common ) diff --git a/vendors/flextesa-lib/tezos_protocol.mli b/vendors/flextesa-lib/tezos_protocol.mli index 4b924f107df469b0aa4f5207590408d640c87d71..f850fbdb45391530a4efcb172a01a428604cf06f 100644 --- a/vendors/flextesa-lib/tezos_protocol.mli +++ b/vendors/flextesa-lib/tezos_protocol.mli @@ -46,7 +46,7 @@ module Voting_period : sig end module Protocol_kind : sig - type t = [`Athens | `Babylon | `Carthage | `Delphi | `Edo | `Alpha] + type t = [`Athens | `Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha] val names : (string * t) list val cmdliner_term : docs:string -> unit -> t Cmdliner.Term.t diff --git a/vendors/flextesa-lib/traffic_generation.ml b/vendors/flextesa-lib/traffic_generation.ml index 2d471c7479c61820e2981e23e613ba0005ad602a..ceb4f0327b985b618a54ea1fc02169e9f0064ad5 100644 --- a/vendors/flextesa-lib/traffic_generation.ml +++ b/vendors/flextesa-lib/traffic_generation.ml @@ -34,7 +34,7 @@ module Michelson = struct ["--wait"; "none"; "originate"; "contract"; name] @ ( match protocol_kind with | `Athens -> ["for"; from] - | `Babylon | `Carthage | `Delphi | `Edo | `Alpha -> [] ) + | `Babylon | `Carthage | `Delphi | `Edo | `Florence | `Alpha -> [] ) @ [ "transferring"; amount; "from"; from; "running"; tmp; "--init" ; init_storage; "--force"; "--burn-cap"; "300000000000" ; (* ; "--fee-cap" ; "20000000000000" *) "--gas-limit"