Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to add a cheaper way to get hash from Plutus data? #6524

Closed
zlonast opened this issue Sep 27, 2024 · 4 comments
Closed

Is it possible to add a cheaper way to get hash from Plutus data? #6524

zlonast opened this issue Sep 27, 2024 · 4 comments
Labels
status: needs triage GH issues that requires triage

Comments

@zlonast
Copy link

zlonast commented Sep 27, 2024

Describe the feature you'd like

I would like to have a feature like this

dataToHash :: ToData a => a -> BuiltinByteString
dataToHash = ...

(I would also like the hash to fit into 28 bytes)

I think it's worth clarifying the context.

        info  = scriptContextTxInfo ctx

        ins   = txInfoInputs info
        refs  = txInfoReferenceInputs info
        outs  = txInfoOutputs info
        range = txInfoValidRange info

        hash = blake2b_224 . serialiseData . toBuiltinData $ (ins, refs, outs, range)

Describe alternatives you've considered

For now I use the following implementation

dataToBlake :: ToData a => a -> BuiltinByteString
dataToBlake = blake2b_224 . serialiseData . toBuiltinData
@github-actions github-actions bot added the status: needs triage GH issues that requires triage label Sep 27, 2024
@effectfully
Copy link
Contributor

effectfully commented Sep 27, 2024

For now I use the following implementation

And you are not satisfied with that and believe that it can be improved somehow? How? I think It's toBuiltinData that is the bottleneck here, so even if we create a builtin for something like blake2b_224 . serialiseData, I don't feel like it'll help much. And given that ToData is a Plinth type class, toBuiltinData is gonna stay expensive, unless we provide a way to serialize the AST of any Plutus value, which is not only gonna break parametricity for the entirety of Plutus (and parametricity is a hill that some of us are willing to die on, see #5440), but also is probably not gonna respect beta-equality, i.e. will basically wildly misbehave.

So I'm not sure what you're proposing here.

@zlonast
Copy link
Author

zlonast commented Sep 27, 2024

Thanks for your the answer, I think I see what you're talking about.

So I'm not sure what you're proposing here.

I was looking for answers here on where to find performance for not very meaningful conversions to Data and Cborg.

but also is probably not gonna respect beta-equality, i.e. will basically wildly misbehave.

It seems to me that beta-equality is not very important in such cases and is not a very unsafe thing.

unless we provide a way to serialize the AST of any Plutus value, which is not only gonna break parametricity for the entirety of Plutus

Perhaps I don't fully understand why breaking parametricity is a problem for a user who wants to take responsibility.

Plutus Core is the low-level language, it's okay for people to have to know what they're doing.

Why do we need static types if we expect people to know what they're doing?

🤔

@colll78
Copy link
Contributor

colll78 commented Sep 30, 2024

I'm assuming the code you are interested in optimizing is from here

The vast majority of the budget from this contract is consumed by the conversion of the script context from and to data encoding.

symbolicVerifier :: SetupBytes -> ProofBytes -> ScriptContext -> Bool
symbolicVerifier contract proof ctx = ...
        info  = scriptContextTxInfo ctx
        ins   = txInfoInputs info
        refs  = txInfoReferenceInputs info
        outs  = txInfoOutputs info
        range = txInfoValidRange info
        hash = blake2b_224 . serialiseData . toBuiltinData $ (ins, refs, outs, range)

To

symbolicVerifier :: SetupBytes -> BuiltinData -> BuiltinUnit
symbolicVerifier contract ctx =
    -- Verifying the Plonk `proof` for the `contract` on the transaction data encoded as `input`
    verify @PlonkPlutus @HaskellCore contract input proof
    where
      ctxFields = BI.snd (BI.unsafeDataAsConstr ctx)
      info = BI.head ctxFields 
      
      -- Extract redeemer from ScriptContext
      proof = unsafeFromBuiltinData @SetupBytes (BI.head $ BI.tail ctxFields)
      
      -- Extracting transaction data
      infoFields  = BI.snd (BI.unsafeDataAsConstr (BI.head ctxFields))
      ins = BI.head infoFields
      info_before_ref_inputs = BI.tail txInfo
      refs = BI.head info_before_ref_inputs
      info_before_outputs = BI.tail info_before_ref_inputs
      outs = BI.head info_before_outputs
      range = BI.head BI.tail $ BI.tail $ BI.tail $ BI.tail $ BI.tail info_before_outputs

      -- Computing public input from the transaction data
      txData = BI.mkConstr ins $ BI.mkCons refs $ BI.mkCons outs $ BI.mkConstr range $ BI.mkNilData BI.unitval
      input = toInput . blake2b_224 . serialiseData $ txData 

@zlonast
Copy link
Author

zlonast commented Oct 1, 2024

I'm assuming the code you are interested in optimizing is from here

The vast majority of the budget from this contract is consumed by the conversion of the script context from and to data encoding.

Thank you very much, I really missed this optimization path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: needs triage GH issues that requires triage
Projects
None yet
Development

No branches or pull requests

3 participants