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

Basic groups inside arrays support. #120

Merged
merged 1 commit into from
Dec 20, 2022
Merged

Conversation

rooooooooob
Copy link
Collaborator

e.g.:

foo = (uint, text)
bar = [
  foos: [* foo],
]

which if you had n foos would be a 2 * n long CBOR array as there's no wrapping map/array around the basic group foo. This can be done in some CDDL specs as a space optimization.

e.g.:
```
foo = (uint, text)
bar = [
  foos: [* foo],
]
```

which if you had `n` foos would be a `2 * n` long CBOR array as there's
no wrapping map/array around the basic group `foo`. This can be done in
some CDDL specs as a space optimization.
@@ -1451,20 +1481,39 @@ impl GenerationScope {
if CLI_ARGS.preserve_encodings {
deser_code.content
.line(&format!("let len = {}.array_sz()?;", deserializer_name))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore this added mut. If we need to make any other changes to this PR I''ll remove it in that commit, otherwise we can remove it when we fix the other warnings in cddl-codegen.

@@ -18,6 +18,11 @@ bar = {

plain = (d: #6.23(uint), e: tagged_text)
outer = [a: uint, b: plain, c: "some text"]
plain_arrays = [
; this is not supported right now. When single-element arrays are supported remove this.
; single: [plain],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we get around this in babbage.cddl by creating another truct like:

single_plain = [plain]
plain_arrays = [
    single: single_plain,
    ...
]

so it's not super high priority to support this, but it would be good if we did when there are less high priority things. I made an issue here: #121

let orig_bytes = orig.to_bytes();
print_cbor_types("orig", &orig_bytes);
let mut deserializer = Deserializer::from(std::io::Cursor::new(orig_bytes.clone()));
let deser = T::deserialize(&mut deserializer).unwrap();
print_cbor_types("deser", &deser.to_bytes());
assert_eq!(orig.to_bytes(), deser.to_bytes());
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check was never failing in this PR, but I just added it in just to be sure. It can't hurt.

//let array_wrapper_name = element_type.name_as_wasm_array();
//types.create_and_register_array_type(element_type, &array_wrapper_name)
if let ConceptualRustType::Rust(element_ident) = &element_type.conceptual_type {
types.set_rep_if_plain_group(parent_visitor, element_ident, Representation::Array);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what we had been doing previously. Ideally we shouldn't assume anything about the encoding for basic(plain) groups (i.e. foo = (uint, uint)). This was done back at the very start (2 1/2 years ago+) as the only plain groups we had to deal with then were things like:

; plain groups defined here
multisig_pubkey = (0, addr_keyhash)
multisig_all = (1, [ * multisig_script ])
multisig_any = (2, [ * multisig_script ])
multisig_n_of_k = (3, n: uint, [ * multisig_script ])

; then we encountered them embedded in an array-encoded group choice
multisig_script =
  [ multisig_pubkey
  // multisig_all
  // multisig_any
  // multisig_n_of_k
  ]

and this made it easier to implement that and let you serialize individual variants of that enum outside of the enum and still end up with a valid multisig_script (which would make more sense to users of CML) even though strictly according to the CDDL if you serialized just a multisig_pubkey you wouldn't get the outer array (which might confuse users of CML despite being truer to the CDDL spec). If we're being totally true to the CDDL this should only be dealt with there and we would get rid of the DeserializeEmbeddedGroup and SerializeEmbeddedGroup traits entirely and have the regular Serialize and Deserialize traits do that behavior. Either that or keep those traits and only implement those traits for plain groups and not implement the direct Serialize/Deserialize traits for them. Unfortunately with preserve-encodings=true this would mean you would have to store the array encoding variable in the enum so you'd end up with so it's possible we want to just keep this how it is. It does, however, make the code surrounding plain groups fiddlier and annoying.

Basic(plain) groups have no encoding naturally, and are only a thing when it's embedded elsewhere, but that should be a detail there, not within the basic group itself. This technically stops us from supporting a plain group being used in both a map and an array, although we've never seen a CDDL definition that does that and it's probably pretty rare.

I didn't make this change here since it would've been a bigger change (and would make the generated code for group choices like the above uglier and possibly surprising to CML users) and this probably isn't high priority.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: If we ever decide to be totally faithful to the CDDL definition regarding plain groups, we could still always rewrite the CDDL in the above as:

multisig_pubkey = [0, addr_keyhash]
multisig_all = [1, [ * multisig_script ]]
multisig_any = [2, [ * multisig_script ]]
multisig_n_of_k = [3, n: uint, [ * multisig_script ]]

multisig_script =
   multisig_pubkey
  / multisig_all
  / multisig_any
  / multisig_n_of_k

to get the current behavior. I'm not sure why they were written in the spec as plain groups to be honest. Maybe to make it more obvious that every mutlisig_script variant is an array-encoded group?

@rooooooooob
Copy link
Collaborator Author

For context, this was needed to generate the CIP-36 library for catalyst.

@rooooooooob
Copy link
Collaborator Author

Yes, that was the part that we couldn't generate.

@rooooooooob rooooooooob merged commit 3f8acf9 into master Dec 20, 2022
rooooooooob added a commit that referenced this pull request Dec 26, 2023
Specifically tests for support for #121 for plain groups.

For multi arrays covered by #120
For single ones covered by #210

We are keeping #121 open for now as the case for single non-plain-groups
e.g. `[uint]` is not covered. We've yet to see this used anywhere in
Cardano so it's low priority to fix.
rooooooooob added a commit that referenced this pull request Dec 27, 2023
Specifically tests for support for #121 for plain groups.

For multi arrays covered by #120
For single ones covered by #210

We are keeping #121 open for now as the case for single non-plain-groups
e.g. `[uint]` is not covered. We've yet to see this used anywhere in
Cardano so it's low priority to fix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants