The clones are cheap enough here that we likely don't need to worry about the cost of cloning; and this removes a significant foot-gun where you can wipe out the logs/labels by accessing the other field.
This refactors things so that eval_phase_two can expose logs even when the script succeeds.
It also enriches traces to be either Logs or Labels, so that we can tell the difference between the two when inspecting the traces.
* Fix: Deeply nested assignments would offset the new columns count calculation. Now we track relevant columns and their path to ensure each row has wildcards if they don't contain the relevant column
* Add test plus clippy fix
* Clippy fix
* New version clippy fix
This is only a start. It compiles, but with a few TODOs left open. In particular, it doesn't currently handle constants depending on other constants or functions; nor does it hoist constants.
Unfortunately, as documented in:
https://github.com/IntersectMBO/cardano-ledger/issues/4571
Some Option fields in the script context certificates are going to
remain set to None, at least until the next Hard fork. There's a risk
that people permanently lock their funds if they expect deposits on
registration credentials to ever be `Some`.
So, we introduce a special type that emulate an `Option` that can only
ever be `None`. We call it `Never` and it is the first type of this
kind (i.e. with constructors indexes not starting at 0).
This covers every proposal procedures but protocol parameters, this
one is yet to be done. It spans over 30+ fields, and felt like it is a
big enough piece to tackle it on its own.
Alongside a bunch of other stuff from the coverage list. In
particular, the mint transaction contains:
- reference inputs
- multiple outputs, with assets, and type-0, type-1 and type-6
addresses.
- an output with a datum hash
- an output with an inline script
- carries an extra datum witness, preimage of the embedded hash
- mint, with 2 policies purposely ordered wrongly, with 1 and 2
assets purposely ordered wrong. One of the mint is actually a
burn (i.e. negative quantity)
This is intense, as we still want to preserve the serializer for V1 &
V2, and I've tried as much as possible to avoid polluting the
application layer with many enum types such as:
```
pub enum TxOut {
V1(TransactionOutput),
V2(TransactionOutput),
V3(TransactionOutput),
}
```
Those types make working with the script context cumbersome, and are
only truly required to provide different serialisation strategies. So
instead, we keep one top-level `TxInfo V1/V2/V3` type, and we ensure
to pass serialization strategies as type wrappers.
This way, the strategy propagates through the structure up until it's
eliminated when it reaches the relevant types.
All-in-all, this strikes a correct balance between maintainability and
repetition; and it makes it possible to define _different but mostly
identical_ encoders for the various versions.
With it, I've been able to successfully encode a V3 script context and
match it against one produced using the Haskell libraries. More to
come.
And also return a structured output as JSON, so it's more easily used
by other tools.
```
Parsing script context
Simulating 78ec148ea647cf9969446891af31939c5d57b275a2455706782c6183ef0b62f1
Redeemer Spend → 0
{"mem":151993,"cpu":58180696}
```
The current implementation assumed that ALL withdrawals present in a
transaction had to be locked by a script and failed otherwise. But a
transaction can actually be composed of both. So instead of failing,
we should rather just ignore withdrawals that can't be referenced by
redeemers.