-
Notifications
You must be signed in to change notification settings - Fork 88
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
Introduce strict equality check for PlutusTx Value #709
Conversation
Transactions CostsSizes and execution budgets for Hydra protocol transactions. Note that unlisted parameters are currently using
Script summary
Cost of Init Transaction
Cost of Commit TransactionCurrently only one UTxO per commit allowed (this is about to change soon)
Cost of CollectCom Transaction
Cost of Close Transaction
Cost of Contest Transaction
Cost of Abort TransactionSome variation because of random mixture of still initial and already committed outputs.
Cost of FanOut TransactionInvolves spending head output and burning head tokens. Uses ada-only UTxO for better comparability.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change looks good. But want all core contributors on Hydra to see and approve this (it's important to know)
-- lists and Map equality is implemented. Instead we can be more strict and | ||
-- require EXACTLY the same value and compare using the serialised bytes. | ||
(===!) :: Value -> Value -> Bool | ||
(===!) val val' = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is ===
or ==!
already taken?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I first went with '===' but then thought to add extra sprinkle using '!' because this is a strict check 😀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My intuition would not have associated the !
with strictness here. Besides it has nothing to do with evaluation strictness. Let's call it more an exact equality. Also, other readers might confuse ===!
with !=
from other languages. So I would remove the !
and just stick with ===
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine by me, renamed!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello!
I was trying to compare results using (===!):
(===!) :: LedgerApiV2.Value -> LedgerApiV2.Value -> Bool
(===!) val val' =
TxBuiltins.serialiseData (LedgerApiV2.toBuiltinData val) == TxBuiltins.serialiseData (LedgerApiV2.toBuiltinData val')
But got an error:
Eval Error: CodecError (DeserialiseFailure 2663 "BadEncoding (0x0000004231c2aa77,S {currPtr = 0x0000004231c2a04e, usedBits = 3}) \"Forbidden builtin function: (builtin serialiseData)\"")
Any idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to run it using protocol version >= 7.0
. The serialiseData
builtin was enabled in version 7 of the ledger/plutus interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @ch1bo !
Im still trying to build and run with the serialiseData to compare results of used resources, but I'm getting the same error "Forbidden builtin function: (builtin serialiseData)".
I just updated Plutus Apps to 1.1.0, the last release and updated cabal and project file according to the files in Plutus Apps.
What else I need to Update?
And also, I let a question for you in cardano stakoverflow... I would be happy if you can help me with that too
Thank you!!!!!
PD: I think I figured it out... you are using your own plutus: hydra-plutus... Im sorry I got this so late! :p
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not "an own plutus", but we are not using plutus-apps. I don't know where you need to do the setting there, but you want to use protocol version >= 7
when you run the scripts by your plutus interpreter (e.g. in a cardano-ledger
or a simulator or so).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you brother!
I just realize that basic stuff about the protocol version I was using to do the evaluation. Now it works!
The method with serialiseData is the best I tested by now. With 20 different tokens, using your way, ExMemory 7294670, mine: ExMemory 9089316, and with (==), ExMemory 13382024. As you can see it serialiseData is almost the half of the normal equality.
Im about to use your way of comparing in a production contracts Im developing. I really need the extra free mem I getting now.
But still I dont really get in full clarity in what kind of scenarios VALUES are not normalized, not ordered and with cs or tn repeated and this way of comparing can fail.
Im using off chain code to create the transactions with lucid framework in a frontend.
Where comes the part that creates the list of values, normalized or not?
I need to understand a little more that to feel more safe in using your way or mine.
Thank you so much
-- require EXACTLY the same value and compare using the serialised bytes. | ||
(===!) :: Value -> Value -> Bool | ||
(===!) val val' = | ||
serialiseData (toBuiltinData val) == serialiseData (toBuiltinData val') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you also tried comparing the hashes or doing an explicit loop through the value elements?
Asked differently, do we know if this is the cheapest way to do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tried it but will do and compare the results.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the logbook entry here and it shows that serializing data is our best bet. Perhaps I should try alternative implementation where I don't rely on plutusTx functions like flattenValue
and valueOf
but I didn't see anything that would make them slower then they need be.
Why
We found out that equality check
(==)
onValue
is expensive inPlutusTx
. Values are implemented as map of maps and map here is just an associative list and this check cares to be able to find the appropriate value for the key anywhere in this list.Since we know that two values and their order should be the same we can leverage this to serialize the data
and then do equality check on
BuiltinBytestring
which is cheaper.What
Introduce a new function to do the strict equality check between serialized representation of two Values.
To check before merging: