cardano-foundation / cardano-wallet

HTTP server & command-line for managing UTxOs and HD wallets in Cardano.
Apache License 2.0
767 stars 213 forks source link

Submitting transactions with ad-hoc datums (and redeemers) #3379

Open hasufell opened 2 years ago

hasufell commented 2 years ago

The problem that you wish to solve

I'm trying to figure out how to create a script transaction without the plutus PAB backend. I have a use case where I want to be able to send arbitrary datums (and redeemers) to a script, without going through the PAB. The nodes will reject invalid datums anyway. And PAB requires explicit knowledge about endpoints, which I don't have.

Currently there are two ways afais:

  1. You can create an unbalanced transaction with cardano-cli transaction build, which is flexible enough and then shove it through the balance endpoint. However, this is poor usability, because it requires dealing with a cli interface in addition to the wallet backend.
  2. You can try to figure out how to use the ledger manually to create an unbalanced transaction. This is potentially error prone and subject to the constantly changing internal API and types.

Description

The main culprit seems to be the diverging of TxOut:

-- | A transaction output, consisting of a target address, a value, and optionally a datum hash.
data TxOut = TxOut {
    txOutAddress   :: Address,
    txOutValue     :: Value,
    txOutDatumHash :: Maybe DatumHash
    }

In the swagger spec, that's here: https://github.com/input-output-hk/cardano-wallet/blob/315ee078e7466147c985155fbc0bccfc176831a3/specifications/api/swagger.yaml#L1119-L1131

And affecting the transactions-construct endpoint.


So the constructTransaction should maybe accept an arbitrary optional json value that represents a plutus datum. Same goes for redeemer.

Implementation suggestions

Two example plutus datums are:

  1. {"constructor":0,"fields":[{"bytes":"abcdefg"}]}
  2. {"constructor":0,"fields":[{"constructor":0,"fields":[]}]}

So the wallet should probably accept Aeson.Value and then use the logic from the node to validate/convert: https://github.com/input-output-hk/cardano-node/blob/0cd6878769a10097e7c780e15efb9919fb94f669/cardano-api/src/Cardano/Api/ScriptData.hs#L480-L532

Hashing and serialisation is done here: https://github.com/input-output-hk/cardano-node/blob/0cd6878769a10097e7c780e15efb9919fb94f669/cardano-api/src/Cardano/Api/ScriptData.hs#L109-L137


Looking at plutus itself, there are a couple of interesting places that show how it handles e.g. datum:

  1. mustPayToTheScript: https://github.com/input-output-hk/plutus-apps/blob/73e5f5ea613a7000da02b4b72900ae6ae1e36a95/plutus-ledger-constraints/src/Ledger/Constraints/TxConstraints.hs#L292
  2. processContraint: https://github.com/input-output-hk/plutus-apps/blob/73e5f5ea613a7000da02b4b72900ae6ae1e36a95/plutus-ledger-constraints/src/Ledger/Constraints/TxConstraints.hs#L292
  3. addOwnOutput: https://github.com/input-output-hk/plutus-apps/blob/73e5f5ea613a7000da02b4b72900ae6ae1e36a95/plutus-ledger-constraints/src/Ledger/Constraints/OffChain.hs#L510-L527
  4. mkTxt: https://github.com/input-output-hk/plutus-apps/blob/73e5f5ea613a7000da02b4b72900ae6ae1e36a95/plutus-ledger-constraints/src/Ledger/Constraints/OffChain.hs#L412-L420

cardano-cli code for transaction build: https://github.com/input-output-hk/cardano-node/blob/42809ad3d420f0695eb147d4c66b90573d27cafd/cardano-cli/src/Cardano/CLI/Shelley/Run/Transaction.hs#L436-L606

hasufell commented 2 years ago

@jonathanknowles @migamake

jonathanknowles commented 2 years ago

Hi @hasufell

Many thanks for creating this issue. I'll make sure that this issue is raised within our team.

HeinrichApfelmus commented 1 year ago

Well, @jonathanknowles , what happened to this issue? 😂