blockfrost / openapi

OpenAPI specification for Blockfrost.io service
https://docs.blockfrost.io
MIT License
22 stars 16 forks source link

Please add two endpoints with an ability to calculate Plutus script execution units #169

Closed matiwinnetou closed 2 years ago

matiwinnetou commented 2 years ago

Input: Plutus Script Output: CBOR representation of compiled Plutus Script + metadata

Input: Id of Plutus Script Output: CBOR representation of compiled Plutus Script + metadata

It would be highly appreciated if a developer could pass only id of script and script could be looked up by blockfrost in cardano-db. This will make it easier for clients because they will not need to know the whole body of Plutus Script.

alessandrokonrad commented 2 years ago

It would be highly appreciated if a developer could pass only id of script and script could be looked up by blockfrost in cardano-db. This will make it easier for clients because they will not need to know the whole body of Plutus Script.

In order to calculate ex units properly, the whole transaction context needs to be taken into consideration as well. So you need the script, datums, redeemers and the context of the tx, like inputs, ouputs, minting etc.

So instead of sending only the script, it's better to send a raw tx in cbor format.

matiwinnetou commented 2 years ago

It would be highly appreciated if a developer could pass only id of script and script could be looked up by blockfrost in cardano-db. This will make it easier for clients because they will not need to know the whole body of Plutus Script.

In order to calculate ex units properly, the whole transaction context needs to be taken into consideration as well. So you need the script, datums, redeemers and the context of the tx, like inputs, ouputs, minting etc.

@satran004 / @mmahut where you aware of it?

satran004 commented 2 years ago

That's right @matiwinnetou .
Probably, Endpoint-1 : To compile a plutus script to cbor format. Endpoint -2 :
Input > Either raw txn in cbor or txn in Json format. Output > Exec Unit in json

Mercurial commented 2 years ago

I just wanted to comment to say that I also support this idea, hopefully it gets implemented!

matiwinnetou commented 2 years ago

@mmahut Cardano Fans could sponsor this work if amount in ADA is reasonable. Please contact us on fanscardano@gmail.com

Since we are developers ourselves we do understand that infrastructure doesn't magically appear out of nowhere, that devs need to be paid.

sorki commented 2 years ago

Sounds good to me, there are few complications: 1) Compiling Plutus scripts depends on the version of the Plutus compiler and the accompanying toolchain - different versions will produce different Plutus Core and the resulting CBOR, which means the script address will change as well. I think that the recommended approach is using Nix and pinned dependencies and updating the toolchain only when the script and its address is allowed to change (and accounted for with the rest of the application).

Plutus script API changes as well so if we would update the toolchain behind the endpoint it could cause the old scripts to fail compilation.

2) Script evaluation needs all of the script inputs, at least a Datum and Redeemer but I think @alessandrokonrad is right and the raw transaction is needed since the third script parameter is a ScriptContext containing additional transaction data.

It would be highly appreciated if a developer could pass only id of script and script could be looked up by blockfrost in cardano-db. This will make it easier for clients because they will not need to know the whole body of Plutus Script.

This is already possible for scripts executed at least once using scripts/{script_hash}/cbor - https://docs.blockfrost.io/#tag/Cardano-Scripts/paths/~1scripts~1{script_hash}~1cbor/get

matiwinnetou commented 2 years ago

I think this is something that could also be worked out right? I see this is more complicated so will be harder to maintain but it is soo important. Perhaps we could have multiple versions supported, a path param /v1/ /v2, etc which binds to specific Plutus version?

Sounds good to me, there are few complications:

  1. Compiling Plutus scripts depends on the version of the Plutus compiler and the accompanying toolchain - different versions will produce different Plutus Core and the resulting CBOR, which means the script address will change as well. I think that the recommended approach is using Nix and pinned dependencies and updating the toolchain only when the script and its address is allowed to change (and accounted for with the rest of the application). Plutus script API changes as well so if we would update the toolchain behind the endpoint it could cause the old scripts to fail compilation.
  2. Script evaluation needs all of the script inputs, at least a Datum and Redeemer but I think @alessandrokonrad is right and the raw transaction is needed since the third script parameter is a ScriptContext containing additional transaction data.

It would be highly appreciated if a developer could pass only id of script and script could be looked up by blockfrost in cardano-db. This will make it easier for clients because they will not need to know the whole body of Plutus Script.

This is already possible for scripts executed at least once using scripts/{script_hash}/cbor - https://docs.blockfrost.io/#tag/Cardano-Scripts/paths/~1scripts~1{script_hash}~1cbor/get

matiwinnetou commented 2 years ago

Entry point to ExUnits's eval function: https://github.com/input-output-hk/plutus/blob/master/plutus-ledger-api/src/Plutus/V1/Ledger/Api.hs#L238

sorki commented 2 years ago

I think this is something that could also be worked out right? I see this is more complicated so will be harder to maintain but it is soo important. Perhaps we could have multiple versions supported, a path param /v1/ /v2, etc which binds to specific Plutus version?

Yes, this is doable - we could follow plutus-starter-devcontainer releases

Entry point to ExUnits's eval function: https://github.com/input-output-hk/plutus/blob/master/plutus-ledger-api/src/Plutus/V1/Ledger/Api.hs#L238

Note the [PLC.Data] argument of that function which requires supplying Datum, Redeemer and ScriptContext. The first two are not a problem but reconstructing ScriptContext is not trivial as it contains info about pending transaction. That said I need to test how the function behaves when you e.g. only supply Datum but the validator works with Redeemer as well - my guess is the evaluation in that case won't produce a correct value (i.e. this could work with partial inputs depending on what data the actual validator works with).

alessandrokonrad commented 2 years ago

The first two are not a problem but reconstructing ScriptContext is not trivial as it contains info about pending transaction

ScriptContext is constructed from the tx you build locally, so it does not depend on the blockchain state, however the data structure can be defined arbitrarily and it's not obvious how it looks like or it's kinda hard to extract it from the tx.

But I checked the cardano-ledger source code and found how it's done on the ledger: https://github.com/input-output-hk/cardano-ledger/blob/5527a510306c46c51dae7106eb23d4a0c8009063/eras/alonzo/impl/src/Cardano/Ledger/Alonzo/PlutusScriptApi.hs#L148

With the function collectTwoPhaseScriptInputs we can extract all relevant data directly from a tx. The data are returned in an array, because there could be multiple scripts/redeemers. Then we run evaluateScriptCounting for all data in the array and get the ex units for each redeemer. The evaluateScriptCounting function is here: https://github.com/input-output-hk/plutus/blob/master/plutus-ledger-api/src/Plutus/V1/Ledger/Api.hs#L238

matiwinnetou commented 2 years ago

Is there any update on this? I think @alessandrokonrad and @sorki have some working solution now on Blockfrost or?

mmahut commented 2 years ago

@matiwinnetou we have a possible solution, but sadly still in our backlog.

mmahut commented 2 years ago

This has proven little bit challenging, but after some time, the /utils/tx/evalute endpoint is out!