Hash script data

I wanted to understand a bit better the hash-script-data functionality from cardano-cli. I checked the source code but had no luck in understanding how this hash is made.

From the examples, if we run:

cardano-cli transaction hash-script-data --script-data-value 42

We get the following hash:


However if we try to do a simple SHA256 hash of a 42 value we get:


Also tried in the Plutus object format:

  "constructor": 0,
  "fields": [{
    "int": 42

but none of those match the hash generated by cardano-cli.

Also tried innumerous other alternatives but obviously I’m missing something, anyone knows what’s the process for generating this hash?

Thank you!

1 Like

It’s not a SHA256 hash.

Related topic: Cardano-cli hash-script-data
ScriptData code: cardano-node/ScriptData.hs at 2124712b360b37b5d590279a4674d504dd32eda5 · input-output-hk/cardano-node · GitHub
ScriptData doc: Cardano.Api.ScriptData
CBOR: rfc7049
Hero: @bwbush


Thanks for the references! I was able to reproduce the hash from cardano-cli using libsodium generic-hash and converting the 42 number into CBOR (182a) prior to hashing.

I was trying to do the same for objects though, without luck:

For example, the object mentioned in the other topic:

         "int": 4

I convert it to CBOR A26B636F6E7374727563746F7200666669656C647381A163696E7404 and then try to hash it and I get 9aa23c572ebf5d39113f516d4bbf69d1b9650e55ea63cdd7fb4ee77975def5b0, while if I put that data in a json file and use cardano-cli transaction hash-script-data --script-data-file ./tests/sample.json I get 8bb54ceaee2f57731094a2e96b8ad87bcc8988b1fa838e8c833eb3b72eae29a1

Also tried using bytes instead of UTF string in the CBOR encoding: A24B636F6E7374727563746F7200466669656C647381A143696E7404
which gives me 5677bf1048dad6dce36483d2bec0fafc71f5dc9b01a2b1326c6443c2cd264b50

Even when reading the source code I’m not sure what I may be missing here :frowning:

Anyone has any idea?

I haven’t tracked down the complete answer, which I believe involves finding the schema for how PlutusData is serialized—the information will be in the ledger spec or its implementation.

A partial answer is that one shouldn’t serialize text like "construction". That is too verbose and it is very likely that there is a custom, succinct serialization that is closely related to the CBOR you generated. I’ll poke around in the specs or source code and post here when I find the answer.


That makes sense and is already very helpful! Made me find this which may contain the answer about how PlutusData is encoded into CBOR :slight_smile: definitely looks like my encoding is not correct.

I’ll check that in more detail tomorrow and post here my findings,

Thank you all again for the help :slight_smile:

Alright, looking at the source code it seems the constructor is converted into a tag, based on its index. The values are then converted into a list, which makes the CBOR encoding to be much smaller, makes much more sense.

What I get from the object I mentioned is: D8798104 (Equivalent to 121([4])) - Tag 121, since constructor value is 0 (121 + 0) and a list with values.

Hash turns it into 034eb48ee254d7e58ff9fda1398f8086b9a8c392e63322960137e6c30bbd7bcf, which is still different than cardano-cli output 8bb54ceaee2f57731094a2e96b8ad87bcc8988b1fa838e8c833eb3b72eae29a1 :slightly_frowning_face:

Still seems like a step forward though, feels like we’re getting closer :joy:

If anyone has any idea what I may be missing here let me know


Found the answer for this case :slight_smile: Turns out the list of fields property should be an indefinite length array.

The correct CBOR is: d8799f04ff

d879 - Equivalent to the tag 121
9f - indefinite-length array
04 - The value 4
ff - The list break

Thanks everyone for the inputs, they were really helpful!


This is probably too late but I just found this repo which could be helpful in the future.

Basically this is Intel’s take on CBOR serialization (probably inspired by TinyXML if anyone else remembers old-school libraries)

1 Like

Can you shed some light because I’m missing something.

Using follwoing code

CborWriter w = new CborWriter();
            var encoded = w.Encode();
            var data =  Sodium.Utilities.BinaryToHex(encoded);
            var res = Sodium.GenericHash.Hash(encoded, null, 32);


I’m able to get same hash as for running:
cardano-cli transaction hash-script-data --script-data-value 42

Now I have a json file with simple data:

if I execute cli
cardano-cli transaction hash-script-data --script-data-file cos.json

if I execute:
cardano-cli transaction hash-script-data --script-data-value {“constructor”:0,“fields”:}

However if I execute it in c#:

CborWriter cw = new CborWriter();
            var complexEncoded = cw.Encode();
            var dataComplex = Sodium.Utilities.BinaryToHex(complexEncoded);
            var complexRes = Sodium.GenericHash.Hash(complexEncoded, null, 32);

2b50f0300204565e13018c878fffdfc646f7c8d78fc140e89a3084b6c35c5a90 - hash

  1. Why cardano-cli that takes an file input and the one that takes string value input return different value?
  2. Any idea how to make c# code to return same hash?

I have just checked the new beta version of the
npm i @emurgo/cardano-serialization-lib-nodejs@10.0.0-beta.8

and it works same way as the cardano-cli

import { Buffer } from "buffer";
import * as pp from "@emurgo/cardano-serialization-lib-nodejs"
export const fromHex = (hex) => Buffer.from(hex, "hex");
export const toHex = (bytes) => Buffer.from(bytes).toString("hex");
const datum = pp.PlutusData.new_constr_plutus_data(
var res = pp.hash_plutus_data(datum);