plutus icon indicating copy to clipboard operation
plutus copied to clipboard

What guarantees do we have about about the internal structure of the things in `ScriptContext`?

Open L-as opened this issue 3 years ago • 11 comments

Describe the feature you'd like

I'm specifically wondering about:

  • Internal ordering of entries in maps in ScriptContext.
    • Both for things like txInfoData that don't use the Map constructor and also things like Value that do use it.
  • Is it possible for there to be 0 of a token in a value?
  • Is it possible for there to be an empty CurrencySymbol entry in a value?
  • Internal ordering of entries in sets.
    • E.g. txInfoDCert, txInfoSignatories, and similar.

I already know that inputs are lexicographically ordered as noted in https://github.com/input-output-hk/plutus/issues/4296#issuecomment-1004723515.

The questions about values are e.g. to know whether a naïve equality check represents "real" equality. If you could have 0 of a token, then a Value with 0 of a token would not be equal to one that is otherwise the same but does not include the same, even though they represent the same amount.

Describe alternatives you've considered

No response

L-as avatar Mar 29 '22 16:03 L-as

Re: Value, see https://github.com/input-output-hk/plutus/issues/4258

The questions about values are e.g. to know whether a naïve equality check represents "real" equality.

What kind of naive equality check are you suggesting? Neither equality on the underlying Map representation nor on the Data representation are correct. You want equivalence of Values, which is what the Eq instance we provide does. Anything else isn't correct.

In principle we could require the representation of Value to be normalized, but then we'd have to be very careful to ensure that this property was always maintained.

Internal ordering of entries in maps in ScriptContext. Internal ordering of entries in sets. E.g. txInfoDCert, txInfoSignatories, and similar.

It depends on how they're represented in the ledger. For example, certificates are actually a sequence in the ledger, and so the order will be the same as what the user provided. It would be nice if we could make that clearer. Perhaps we just need a Set newtype to indicate that certain lists don't have a fixed order...

But for things that are set-like we don't provide any ordering guarantees, and I don't think we're likely to. Maybe in the future we will if something like https://github.com/cardano-foundation/CIPs/pull/231 gets accepted.

michaelpj avatar Mar 31 '22 11:03 michaelpj

What kind of naive equality check are you suggesting? Neither equality on the underlying Map representation nor on the Data representation are correct. You want equivalence of Values, which is what the Eq instance we provide does. Anything else isn't correct.

Note that equality (and other relations, like <=) in the ledger semantics behave exactly like that, i.e. adding redundant zeros doesn't affect them (or, equivalently, everything that's not non-zero is zero). So if a relation were finer than that, it wouldn't match the ledger semantics.

WhatisRT avatar Mar 31 '22 11:03 WhatisRT

So is it possible to construct a transaction where we control the order of the entries in txInfoMint? Can we also mint a zero amount?

L-as avatar Mar 31 '22 11:03 L-as

There are no guarantees about the order. I think they are sorted (similar to inputs), but there are some potential subtleties in the implementation that may or may not screw you over if you try to rely on it. And yes, you can always mint zero of something (which of course does nothing but increase fees).

WhatisRT avatar Mar 31 '22 12:03 WhatisRT

@WhatisRT Does minting 0 still run the script? If so, can you also Withdraw 0 ADA from a stake account, running a stake validator in the process?

zygomeb avatar Mar 31 '22 12:03 zygomeb

I'd like to remind you all that this stuff is specified :) If you look in the Shelley formal spec, you will see that the set of minting policies which is run is the support of the Value considered as a finitely-supported-function; i.e. it does not include anything which maps to zero. This is consistent with 0 entries being equivalent to not being present.

michaelpj avatar Mar 31 '22 13:03 michaelpj

Neither equality on the underlying Map representation nor on the Data representation are correct. You want equivalence of Values, which is what the Eq instance we provide does. Anything else isn't correct.

Doesn't the Cardano ledger impl and the CLI already normalize Values when building transactions though?

The CLI seems to do such a thing when building transaction here.

The Cardano ledger impl also seems to maintain sorted Values (and potentially even normalized via prune). I'd assume transforming such a Value (which is a real Map) into the Plutus Value (which is an assoc list) would indeed produce a normalized Value - but I'm not sure if there's more stuff going on in the middle.

Also tangentially related, but the CBOR spec seems to also suggest the encoding of maps be sorted. The Alonzo spec seems to suggest it maintain the "canonical" format, which is also given in the RFC. It seems odd that Plutus's Value (and Map I guess) doesn't maintain this canonical format upon serialization to CBOR. I think the Cardano API Value does maintain this format though. Does that specific section of the spec only apply to the Cardano API and its direct users ....?

I feel confused at the fact that some parts of the official Cardano code seem to consciously try and ensure normalization of Values, whereas other places don't.

In principle we could require the representation of Value to be normalized, but then we'd have to be very careful to ensure that this property was always maintained.

I think it'd be quite doable to maintain normalization, for Values at least, if what is being fed to the script is actually normalized. And from the code, it seems that if we limit ourselves to purely using the cardano-cli for building and submitting transactions, that invariant could potentially already be enforced.

TotallyNotChase avatar Mar 31 '22 14:03 TotallyNotChase

You're mixing some things here. Just because the CLI outputs a certain format it doesn't mean that all transactions have to be of that format. The same goes for this canonical format: this is only used to compute the script integrity hash and doesn't even apply to Value.

Also, the restricting oneself to transactions produced by the cardano-cli is bad, since an attacker can then construct a transaction by hand and break your assumptions. So, be safe, don't peek at internals and interact with Value via the functions provided.

WhatisRT avatar Apr 06 '22 13:04 WhatisRT

Something we observed is that the provided high-level functions are quite expensive in terms of memory and CPU, much more than working directly with the underlying Map representation. With current Plutus limitations, it may be necessary to break the Value abstraction in some complex scripts. I think this can be safe from attacks as long as the scripts are conservative enough to fail when the assumptions are not met.

francolq avatar Apr 06 '22 14:04 francolq

https://github.com/input-output-hk/cardano-ledger/blob/master/eras/shelley-ma/impl/src/Cardano/Ledger/Mary/Value.hs#L382

It very much seems like the sortedness of values is part of the guarantees.

L-as avatar Apr 08 '22 23:04 L-as

I believe we need an objective on coming up with a process to figure out

  1. what kinds of things are there to stay
  2. how to handle and report breaking changes (see also the discussion in #5408 and #4753)

The security of the whole system depends on these things, so it definitely should be prioritized.

effectfully avatar Jul 14 '23 16:07 effectfully