<p><strong>Question 1:</strong> The blog talks about how to handle data concurrently in dapp designs. More explicitly, the case where processes are split across multiple unspent transaction outputs (<code>N</code> outputs) and <strong>batched</strong> into a single transaction for further processing.</p>
<p>In this setup, each output is locked by a script (can be the same script), so to validate that each is correctly spent, validators have to run the script <code>N</code> times. The protocol parameters describe a maximum amount of memory a transaction can consume as a safeguard, the <code>max_tx_ex_mem</code> parameter. Currently, this is set to 14000000 abstract memory units, this is the limit.</p>
<p><strong>Question 2:</strong> The consumption of a script can differ in each transaction, depending on what action is taken by that script. If the script can only perform one action, the consumption would be the same each transaction. If a script can do multiple things, the consumption can differ. To check how much abstract execution units your transaction consumes in total, use the client command,</p>
<pre><code>CARDANO_CLI transaction build \
  --alonzo-era \
  --cardano-mode \
  --testnet-magic &quot;$TESTNET_MAGIC&quot; \
  --change-address &quot;$utxoaddr&quot; \
  --tx-in &quot;$plutusutxotxin&quot; \
  --tx-in-collateral &quot;$txinCollateral&quot; \
  --tx-out &quot;$dummyaddress+10000000&quot; \
  --tx-in-script-file &quot;$plutusscriptinuse&quot; \
  --tx-in-datum-file &quot;$datumfilepath&quot;  \
  --protocol-params-file &quot;$WORK/pparams.json&quot; \
  --tx-in-redeemer-file &quot;$redeemerfilepath&quot; \
  --calculate-plutus-script-cost &quot;$WORK/create-datum-output.scriptcost&quot;
  
  &gt; cat $WORK/create-datum-output.scriptcost
  [
    {
        &quot;executionUnits&quot;: {
            &quot;memory&quot;: 1700,
            &quot;steps&quot;: 476468
        },
        &quot;lovelaceCost&quot;: 133,
        &quot;scriptHash&quot;: &quot;67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656&quot;
    }
]
</code></pre>
<p>For a more in-depth view on how a specific script consumes execution units, have a look at <a href="https://plutus-apps.readthedocs.io/en/latest/plutus/howtos/analysing-scripts.html" rel="nofollow noreferrer">(1)</a></p>

CC BY-SA 4.0
2022-08-15T23:14:00.850Z
Thank you for your answer to my second question and the link in (1). This was useful. For my first question, I don't see how your answer addresses it. I am familiar of how Cardano works. I was confused of why "memory consumption" was taking the aggregate of memory consumed (whatever this means) instead of being a metric of how much memory a system would need to be able to computationally evaluate the scripts.
Jey
CC BY-SA 4.0
2022-08-16T06:55:17.183Z
The key point is that for each output, a script is run for the validation that the output can be spent. Since this blog talked about splitting computation across multiple outputs, the total memory consumption in a transaction that spends multiple of these inputs, is the sum of the memory consume by each validation of an output in that transaction. Aggregate of memory = total memory in the transaction. So, why is the memory consumption the aggregate of all scripts executed? Because the script runs `N` times in these transactions.
Fermat
CC BY-SA 4.0
2022-08-16T10:52:42.973Z
I understand the mechanic but it made no sense to me from a computational point of view. E.g. when I program a script that reads 10 files, compresses the content, and then saves it to disk, the sum of the memory used is of no importance as the files can be processed sequentially. Only if processed in parallel, the sum is important. Likewise, with a transaction consisting of multiple scripts: the minimum memory necessary to validate the transaction is independent of the sum of the memory used. It depends only on the maximum memory used *per script* (plus overhead).
Jey
CC BY-SA 4.0
2022-08-16T11:04:14.910Z
The sum is important since a block producer has to perform the calculation `N` times and would like to be compensated for each run of the script (especially if it fails after the `N-1` check). The memory the blog talks about it the abstract execution unit memory, not the real memory a node might use for validating. Indeed, in a sequential run the ram used by the node might be lower, but this is not of importance. The consumption of the whole transaction matters for the cost made, it is good to remember that we are in a trustless setup.
Fermat
CC BY-SA 4.0
2022-08-09T16:07:44.003Z
2022-08-09T16:07:44.003Z
Fermat
<p>I feel like the memory consumption constraint has never been raised and properly discussed before this blogpost:</p>
<p><a href="https://iohk.io/en/blog/posts/2021/11/16/architecting-dapps-on-the-eutxo-ledger/" rel="nofollow noreferrer">https://iohk.io/en/blog/posts/2021/11/16/architecting-dapps-on-the-eutxo-ledger/</a></p>
<p>It is good to have this pointed out even if it is somehow strange that in comes in the form of a blogpost and so late.</p>
<p>The blogpost says:</p>
<blockquote>
<p>When adopting such a batching pattern, one should bear in mind that,
whenever N orders sitting at the request script are consumed within a
single transaction, the request script will be executed N times on
transaction submission. <strong>Moreover, the memory limit check (triggered
when the transaction is submitted) is realized by aggregating the
memory consumption for each single request script execution, for the
main script execution, and for any MintingPolicy scripts that may also
be executed (i.e., according to protocol design).</strong></p>
</blockquote>
<p>My questions are:</p>
<ol>
<li><p>Why is the memory consumption the aggregate of all scripts executed ? The result of any given script is a boolean and there is no possible dependency of one script to any other (as no script can access any other as you can verify in the Plutus API). Why does the node need so much memory ? Why doesn't it just need the memory needed for the largest script. The memory could be cleared after each script execution.</p>
</li>
<li><p>How can we compute the memory consumption of a script ? An approximate method would help too.</p>
</li>
</ol>

<plutus>
Memory constraints for smart contracts
# Memory constraints for smart contracts

(Asked by: username_0 on 2021-11-30)

I feel like the memory consumption constraint has never been raised and properly discussed before this blogpost:

<https://iohk.io/en/blog/posts/2021/11/16/architecting-dapps-on-the-eutxo-ledger/>

It is good to have this pointed out even if it is somehow strange that in comes in the form of a blogpost and so late.

The blogpost says:

> When adopting such a batching pattern, one should bear in mind that,
> whenever N orders sitting at the request script are consumed within a
> single transaction, the request script will be executed N times on
> transaction submission. **Moreover, the memory limit check (triggered
> when the transaction is submitted) is realized by aggregating the
> memory consumption for each single request script execution, for the
> main script execution, and for any MintingPolicy scripts that may also
> be executed (i.e., according to protocol design).**

My questions are:

1. Why is the memory consumption the aggregate of all scripts executed ? The result of any given script is a boolean and there is no possible dependency of one script to any other (as no script can access any other as you can verify in the Plutus API). Why does the node need so much memory ? Why doesn't it just need the memory needed for the largest script. The memory could be cleared after each script execution.
2. How can we compute the memory consumption of a script ? An approximate method would help too.

**Tags:** plutus

---

## 1 answers

### Answer by username_1 on 2022-08-09. Score: 0

Question 1: The blog talks about how to handle data concurrently in dapp designs. More explicitly, the case where processes are split across multiple unspent transaction outputs (N outputs) and batched into a single transaction for further processing.
In this setup, each output is locked by a script (can be the same script), so to validate that each is correctly spent, validators have to run the script N times. The protocol parameters describe a maximum amount of memory a transaction can consume as a safeguard, the max_tx_ex_mem parameter. Currently, this is set to 14000000 abstract memory units, this is the limit.
Question 2: The consumption of a script can differ in each transaction, depending on what action is taken by that script. If the script can only perform one action, the consumption would be the same each transaction. If a script can do multiple things, the consumption can differ. To check how much abstract execution units your transaction consumes in total, use the client command,
CARDANO_CLI transaction build \
  --alonzo-era \
  --cardano-mode \
  --testnet-magic "$TESTNET_MAGIC" \
  --change-address "$utxoaddr" \
  --tx-in "$plutusutxotxin" \
  --tx-in-collateral "$txinCollateral" \
  --tx-out "$dummyaddress+10000000" \
  --tx-in-script-file "$plutusscriptinuse" \
  --tx-in-datum-file "$datumfilepath"  \
  --protocol-params-file "$WORK/pparams.json" \
  --tx-in-redeemer-file "$redeemerfilepath" \
  --calculate-plutus-script-cost "$WORK/create-datum-output.scriptcost"
  
  > cat $WORK/create-datum-output.scriptcost
  [
    {
        "executionUnits": {
            "memory": 1700,
            "steps": 476468
        },
        "lovelaceCost": 133,
        "scriptHash": "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656"
    }
]

For a more in-depth view on how a specific script consumes execution units, have a look at (1)

> **Comments:**
> **username_0**: Thank you for your answer to my second question and the link in (1). This was useful. For my first question, I don't see how your answer addresses it. I am familiar of how Cardano works. I was confused of why "memory consumption" was taking the aggregate of memory consumed (whatever this means) instead of being a metric of how much memory a system would need to be able to computationally evaluate the scripts.  
> **username_1**: The key point is that for each output, a script is run for the validation that the output can be spent. Since this blog talked about splitting computation across multiple outputs, the total memory consumption in a transaction that spends multiple of these inputs, is the sum of the memory consume by each validation of an output in that transaction. Aggregate of memory = total memory in the transaction. So, why is the memory consumption the aggregate of all scripts executed? Because the script runs `N` times in these transactions.  
> **username_0**: I understand the mechanic but it made no sense to me from a computational point of view. E.g. when I program a script that reads 10 files, compresses the content, and then saves it to disk, the sum of the memory used is of no importance as the files can be processed sequentially. Only if processed in parallel, the sum is important. Likewise, with a transaction consisting of multiple scripts: the minimum memory necessary to validate the transaction is independent of the sum of the memory used. It depends only on the maximum memory used *per script* (plus overhead).  
> **username_1**: The sum is important since a block producer has to perform the calculation `N` times and would like to be compensated for each run of the script (especially if it fails after the `N-1` check). The memory the blog talks about it the abstract execution unit memory, not the real memory a node might use for validating. Indeed, in a sequential run the ram used by the node might be lower, but this is not of importance. The consumption of the whole transaction matters for the cost made, it is good to remember that we are in a trustless setup.  

---

