As the title says, I want to to reimplement the hashing part of a policy script in Python 3. I have already made a post over at forums.cardano.org, and someone has pointed me to the right direction of serializing to CBOR according to the CDDL specs.
Here's the relevant part of the CDDL specifications:
native_script =
[ script_pubkey
// script_all
// script_any
// script_n_of_k
// invalid_before
; Timelock validity intervals are half-open intervals [a, b).
; This field specifies the left (included) endpoint a.
// invalid_hereafter
; Timelock validity intervals are half-open intervals [a, b).
; This field specifies the right (excluded) endpoint b.
]
script_pubkey = (0, addr_keyhash)
script_all = (1, [ * native_script ])
script_any = (2, [ * native_script ])
script_n_of_k = (3, n: uint, [ * native_script ])
invalid_before = (4, uint)
invalid_hereafter = (5, uint)
CBOR and CDDL are both new to me, so I'm not sure if I am doing it right.
According to the above specification, my script
{
"type":"all",
"scripts":[
{
"keyHash":"37c19eca0d623d804bfeb8951bf1eb0f7fe193deeb71793985dbd25e",
"type":"sig"
},
{
"type":"before",
"slot":32241869
}
]
}
would evaluate to:
native_script = [1, [[0, $hash28], [5, uint]]]
Is this correct? Do I need to use any cbor tags for serializing?
Here is my attempt so far (I've tried many variations already, but this feels like the most correct one):
import hashlib
from cbor2 import dumps, loads, shareable_encoder, CBORTag
class Sig:
def __init__(self, hash, slot):
self.hash=hash
self.slot=slot
def default_encoder(encoder,value):
encoder.encode([1, [[0, value.hash.encode()], [5, value.slot]]])
obj=Sig("37c19eca0d623d804bfeb8951bf1eb0f7fe193deeb71793985dbd25e", 32241869)
serialized = dumps(obj, default=default_encoder, value_sharing=False)
print(serialized.hex())
m=hashlib.blake2b(digest_size=28)
m.update(serialized)
print(m.digest().hex())
result = loads(serialized)
print(result)
Needless to say, the code does not calculate me the same policy id as
cardano-cli transaction policyid --script-file test.script
does.
I am using the library cbor2, which seems the best maintained one for python. Also, I use blake2b with digest_size set to 28 bytes since the ledger specs say blake2b_224 is used for multisig scripts. I am however also not sure if the other parameters in the hash function need to be set or not. My haskell skills are also not the best, so trying to look up in the original source code didn't get me very far, and I've tried so now for several hours :-)
If anyone could help me, it'd be very appreciated.