How exactly does Plutus-Core access the Datum, Redeemer and ScriptContext?

Hello everyone,

I’ve been thinking about writing a compiler to convert some alternative programming languages into untyped plutus core.

The spec doesn’t seem to mention how a plutus core program accesses its global arguments though.

I was expecting the program to accept some ‘Data’ arguments, or alternatively to find something like a ‘getArg :: Integer → IO Data’ builtin function. But it doesn’t seem to work like that.

Can anyone here help me understand how exactly a plutus core program accesses its Datum, Redeemer and ScriptContext?

Should the program expression simply be 3 nested lambda functions?

(The spec document I used for reference:


1 Like

So I think I managed to figure it out.

I analyzed the content of the AlwaysSucceeds script in

The AST of this script seems to start with 2 function applications, and then 5 nested lambda expressions. So after the 2 function applications, a function remains that accepts 3 arguments.

Those 3 arguments will probably be the Datum, Redeemer and ScriptContext.

1 Like

PS: the spec document I linked to in my first post isn’t a very good reference as it contains some confusing inconsistencies.

I will try to report them to the maintainers of the plutus-core repository.

Would be curious to know your intended approach.

Seems like a very useful and missing element of the developer ecosystem currently. However a lot of languages will not work well for generating Plutus which is a very limited subset of Haskell. Might need a DSL abstraction to avoid multiple disparate implementations of the generator.

For example:

Solidity (or other user language) → SDK → DSL → Generator → Plutus

What I’d be really interested in, is some kind of “disassembler” for the Plutus core scripts that can be found in smart contract transactions on-chain.

To analyse what it is that is really ensured by these contracts.

And maybe even an “assembler” for the other direction to be able to write contracts without Haskell.

I guess the “assembler” language would be the DSL in @DinoDude’s post. Not sure, how much Haskellisms have to be in there. The specification linked above seems to get along good without them.

Funny you mention that.

My original plan was to create an OpenCL-style DSL, that compiles to plutus-core. My plan was also to write a compiler in javascript, so it could be used in fully decentralized, ipfs-hosted, client-side dapps (using BlockFrost or equivalent for interacting with the blockchain).

But when I finished reading the plutus-core spec, I felt my understanding of plutus-core was incomplete, and I needed a disassembler to analyze some of the existing scripts in order to fill in the gaps.

So I wrote a disassembler in javascript in order to be able to answer my own question above. I will post it on github, and maybe even host a little webinterface for interactive disassembly.

1 Like

I just meant the answer just above mine.

I’d be interested in a link to that report, so I don’t need to stumble over the same inconsistencies when going through the spec. :grinning:

1 Like

Oops, didn’t see that.

I wasn’t really thinking of a DSL as a compilation target for other languages. Rather as something ‘kind-of-high-level’ that can be written directly and understood by 99% of the world’s programmers.

That last requirement essentially means C-like syntax.

I also don’t know how many of the ‘abstract’ typing features of plutus-core (polymorphism etc.) are really necessary for validator scripts. I think that in most financial use-cases these scripts should be exceedingly simple, and can be simply typed at compile-time. Algebraic data types are probably also not necessary.

There is only one ‘Haskellism’ that I haven’t fully figured out yet. There is a clear need for builtin lists, which in plutus-core are implemented as linked-lists. This of course is where all of Haskell’s recursiveness comes in: getting the length, getting an element, mapping, filtering, folding etc… Should the DSL include some builtins that perform these basic functions (allows conventional indexing using brackets)? Or should the DSL allow programming these methods directly (simplifies the compiler a bit)?

I would be nice to hear your thoughts on this.

Perhaps I will start a new thread in the forum where we can discuss the design of this DSL.

The deserializer I used to analyze some existing scripts can now be found on github:


I attempted using TinyCBOR for serialize/de-serialize but I think most people are using cardano-serialization-lib these days and Nami also has a custom extension of that library which adds functionality and fixes some issues.

As for DSL I was thinking of the “minimal intermediate language” that way python, javascript, or whatever language via the SDK can have a consistent API to the Plutus generator. There is no polymorphism or OOP capability so it would really be about the compositional object representation and helper methods you want to provide to perform common tasks in a higher level language abstraction.

Glow attempted something like this but I think development has slowed as they ran into snags trying to support too many platforms due to the lofty goal of being the DSL to all smart contracts. Ultimately this is something that will be needed still in the next 5-10 years as side-chains and cross-chains become standardized.

The plutus scripts use ‘Flat’ encoding, not CBOR, and I’m not sure the cardano-serialization-lib supports that.

1 Like

I thought ScriptData was CBOR hex encoded and therefore the plutus script was hashed as CBOR hex … I guess that is just the transaction containing the output of the compiled plutus script?

That is definitely a new topic and could honestly require a CIP and a month of discussion from people with more expertise than me. Initial thought is there are enough multi-paradigm languages that functional “limitations” could be transcribed. For example it is unpopular but totally possible to write purely functional code in C++ especially with lambdas in newer standards.

Therefore it could be possible to create an interpreter or translator in the DSL to converge upon a more Haskell friendly format. For example using linked lists for arrays, vectors, sets, and other similar “listable” data structures. Any language that has the concept of a function should be supported in the DSL albeit with a heavy amount of helpers or built-ins exposed through language specific SDK as you allude.

Alternative designs worth considering would be MBSE which arguably is what Marlowe is all about.

That’s right. The spending transaction contains the flat encoded Plutus-core script, wrapped twice in a cbor bytearray. They call this wrapping the text envelope (I don’t entirely understand why it is done).

1 Like

Less is more. It conserves bytes and allows for simpler transaction storage on the ledger. It does seem like one layer of compression or a single hashed representation would have been enough though … I obviously don’t entirely understand either :smiley:

Update: I’ve moved the disassembly/decompilation funtionality to GitHub - OpenEngineer/plutus-light: Plutus-Light

1 Like