diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp index e00b5716885..a388936a01d 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp @@ -301,12 +301,14 @@ T deserialize_msgpack_compact(std::vector&& buf, std::function(buf.data())[1]; @@ -316,8 +318,10 @@ T deserialize_msgpack_compact(std::vector&& buf, std::function + static void convert_or_throw(msgpack::object const& val, + std::string const& struct_name, + std::string const& field_name, + T& field) + { + try { + val.convert(field); + } catch (const msgpack::type_error&) { + std::cerr << val << std::endl; + throw_or_abort("error converting into field " + struct_name + "::" + field_name); + } + } + + /// Whether `o` is a non-empty MAP whose first key is an integer. + /// This is the signature of `Format::MsgpackTagged`: int keys for + /// struct field tags and enum variant tags. Legacy `Format::Msgpack` + /// keys are always strings, so a positive-integer first key is a + /// reliable shape discriminator between the two. + static bool is_int_keyed_map(msgpack::object const& o) + { + return o.type == msgpack::type::MAP && o.via.map.size > 0 && + o.via.map.ptr[0].key.type == msgpack::type::POSITIVE_INTEGER; + } + + /// Iterate an int-keyed MAP and invoke `dispatch(tag, val)` for each + /// `(u8, msgpack::object)` entry. The per-tag `switch` inside the + /// caller's lambda decides which field (or variant) to populate; + /// unknown tags fall through to `default` and are silently skipped, + /// matching the `MsgpackTagged` decoder's forward-compat policy + /// (`allow_unknown_tags` / retired tags drained). + template + static void int_map_dispatch(msgpack::object const& o, std::string const& name, Dispatch&& dispatch) + { + for (uint32_t i = 0; i < o.via.map.size; ++i) { + uint8_t tag; + try { + o.via.map.ptr[i].key.convert(tag); + } catch (const msgpack::type_error&) { + std::cerr << o.via.map.ptr[i].key << std::endl; + throw_or_abort("expected u8 tag in int-keyed map for " + name); + } + dispatch(tag, o.via.map.ptr[i].val); + } + } + + /// Cap a `MAP` or `ARRAY` entry count against `active + reserved`. + /// Under-length wires are caught downstream (`conv_fld_from_array` + /// errors out of bounds; `conv_fld_from_kvmap` errors on missing + /// required keys), so we only need the upper bound here. + /// + /// * Up to `reserved` extra trailing entries are tolerated as + /// retired fields (`#[tagged(reserved(...))]` on the Rust side). + /// * Anything beyond that is forward-compat drift that the + /// producer only emits when newer fields were added. The + /// Rust-side cue is `#[tagged(allow_unknown_tags)]`; the + /// message points at it so a reviewer can see the opt-in. + static void check_size(uint32_t actual, std::string const& name, uint32_t active, uint32_t reserved) + { + uint32_t max_size = active + reserved; + if (actual > max_size) { + throw_or_abort(name + " has " + std::to_string(actual) + " entries but at most " + + std::to_string(max_size) + " are expected (" + std::to_string(active) + " active + " + + std::to_string(reserved) + + " reserved); opt into `#[tagged(allow_unknown_tags)]` on the Rust type to accept extras"); + } + } }; } // namespace Acir @@ -198,44 +276,102 @@ struct BinaryFieldOp { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'BinaryFieldOp'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; + try { o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("expected u8 variant tag for enum 'BinaryFieldOp'"); + } + switch (tag) { + case 0: { + Add v; + value = v; + break; + } + case 1: { + Sub v; + value = v; + break; + } + case 2: { + Mul v; + value = v; + break; + } + case 3: { + Div v; + value = v; + break; + } + case 4: { + IntegerDiv v; + value = v; + break; + } + case 5: { + Equals v; + value = v; + break; + } + case 6: { + LessThan v; + value = v; + break; + } + case 7: { + LessThanEquals v; + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'BinaryFieldOp' enum variant tag: " + std::to_string(tag)); } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'BinaryFieldOp'"); - } - if (tag == "Add") { - Add v; - value = v; - } else if (tag == "Sub") { - Sub v; - value = v; - } else if (tag == "Mul") { - Mul v; - value = v; - } else if (tag == "Div") { - Div v; - value = v; - } else if (tag == "IntegerDiv") { - IntegerDiv v; - value = v; - } else if (tag == "Equals") { - Equals v; - value = v; - } else if (tag == "LessThan") { - LessThan v; - value = v; - } else if (tag == "LessThanEquals") { - LessThanEquals v; - value = v; } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'BinaryFieldOp' enum variant: " + tag); + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; + try { + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting tag to string for enum 'BinaryFieldOp'"); + } + if (tag == "Add") { + Add v; + value = v; + } else if (tag == "Sub") { + Sub v; + value = v; + } else if (tag == "Mul") { + Mul v; + value = v; + } else if (tag == "Div") { + Div v; + value = v; + } else if (tag == "IntegerDiv") { + IntegerDiv v; + value = v; + } else if (tag == "Equals") { + Equals v; + value = v; + } else if (tag == "LessThan") { + LessThan v; + value = v; + } else if (tag == "LessThanEquals") { + LessThanEquals v; + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'BinaryFieldOp' enum variant: " + tag); + } } } }; @@ -410,56 +546,134 @@ struct BinaryIntOp { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'BinaryIntOp'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; + try { o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("expected u8 variant tag for enum 'BinaryIntOp'"); + } + switch (tag) { + case 0: { + Add v; + value = v; + break; + } + case 1: { + Sub v; + value = v; + break; + } + case 2: { + Mul v; + value = v; + break; + } + case 3: { + Div v; + value = v; + break; + } + case 4: { + Equals v; + value = v; + break; + } + case 5: { + LessThan v; + value = v; + break; + } + case 6: { + LessThanEquals v; + value = v; + break; + } + case 7: { + And v; + value = v; + break; + } + case 8: { + Or v; + value = v; + break; + } + case 9: { + Xor v; + value = v; + break; + } + case 10: { + Shl v; + value = v; + break; + } + case 11: { + Shr v; + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'BinaryIntOp' enum variant tag: " + std::to_string(tag)); } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'BinaryIntOp'"); - } - if (tag == "Add") { - Add v; - value = v; - } else if (tag == "Sub") { - Sub v; - value = v; - } else if (tag == "Mul") { - Mul v; - value = v; - } else if (tag == "Div") { - Div v; - value = v; - } else if (tag == "Equals") { - Equals v; - value = v; - } else if (tag == "LessThan") { - LessThan v; - value = v; - } else if (tag == "LessThanEquals") { - LessThanEquals v; - value = v; - } else if (tag == "And") { - And v; - value = v; - } else if (tag == "Or") { - Or v; - value = v; - } else if (tag == "Xor") { - Xor v; - value = v; - } else if (tag == "Shl") { - Shl v; - value = v; - } else if (tag == "Shr") { - Shr v; - value = v; } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'BinaryIntOp' enum variant: " + tag); + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; + try { + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting tag to string for enum 'BinaryIntOp'"); + } + if (tag == "Add") { + Add v; + value = v; + } else if (tag == "Sub") { + Sub v; + value = v; + } else if (tag == "Mul") { + Mul v; + value = v; + } else if (tag == "Div") { + Div v; + value = v; + } else if (tag == "Equals") { + Equals v; + value = v; + } else if (tag == "LessThan") { + LessThan v; + value = v; + } else if (tag == "LessThanEquals") { + LessThanEquals v; + value = v; + } else if (tag == "And") { + And v; + value = v; + } else if (tag == "Or") { + Or v; + value = v; + } else if (tag == "Xor") { + Xor v; + value = v; + } else if (tag == "Shl") { + Shl v; + value = v; + } else if (tag == "Shr") { + Shr v; + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'BinaryIntOp' enum variant: " + tag); + } } } }; @@ -568,38 +782,86 @@ struct IntegerBitSize { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'IntegerBitSize'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; + try { o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("expected u8 variant tag for enum 'IntegerBitSize'"); + } + switch (tag) { + case 0: { + U1 v; + value = v; + break; + } + case 1: { + U8 v; + value = v; + break; + } + case 2: { + U16 v; + value = v; + break; + } + case 3: { + U32 v; + value = v; + break; + } + case 4: { + U64 v; + value = v; + break; + } + case 5: { + U128 v; + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'IntegerBitSize' enum variant tag: " + std::to_string(tag)); } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'IntegerBitSize'"); - } - if (tag == "U1") { - U1 v; - value = v; - } else if (tag == "U8") { - U8 v; - value = v; - } else if (tag == "U16") { - U16 v; - value = v; - } else if (tag == "U32") { - U32 v; - value = v; - } else if (tag == "U64") { - U64 v; - value = v; - } else if (tag == "U128") { - U128 v; - value = v; } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'IntegerBitSize' enum variant: " + tag); + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; + try { + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting tag to string for enum 'IntegerBitSize'"); + } + if (tag == "U1") { + U1 v; + value = v; + } else if (tag == "U8") { + U8 v; + value = v; + } else if (tag == "U16") { + U16 v; + value = v; + } else if (tag == "U32") { + U32 v; + value = v; + } else if (tag == "U64") { + U64 v; + value = v; + } else if (tag == "U128") { + U128 v; + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'IntegerBitSize' enum variant: " + tag); + } } } }; @@ -675,33 +937,67 @@ struct BitSize { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'BitSize'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; + try { o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("expected u8 variant tag for enum 'BitSize'"); + } + switch (tag) { + case 0: { + Field v; + value = v; + break; + } + case 1: { + Integer v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BitSize::Integer'"); + } + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'BitSize' enum variant tag: " + std::to_string(tag)); } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'BitSize'"); - } - if (tag == "Field") { - Field v; - value = v; - } else if (tag == "Integer") { - Integer v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BitSize::Integer'"); + throw_or_abort("error converting tag to string for enum 'BitSize'"); + } + if (tag == "Field") { + Field v; + value = v; + } else if (tag == "Integer") { + Integer v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BitSize::Integer'"); + } + + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'BitSize' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'BitSize' enum variant: " + tag); } } }; @@ -788,40 +1084,80 @@ struct MemoryAddress { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'MemoryAddress'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'MemoryAddress'"); - } - if (tag == "Direct") { - Direct v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'MemoryAddress::Direct'"); + throw_or_abort("expected u8 variant tag for enum 'MemoryAddress'"); + } + switch (tag) { + case 0: { + Direct v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'MemoryAddress::Direct'"); + } + value = v; + break; + } + case 1: { + Relative v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'MemoryAddress::Relative'"); + } + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'MemoryAddress' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "Relative") { - Relative v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'MemoryAddress::Relative'"); + throw_or_abort("error converting tag to string for enum 'MemoryAddress'"); + } + if (tag == "Direct") { + Direct v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'MemoryAddress::Direct'"); + } + + value = v; + } else if (tag == "Relative") { + Relative v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'MemoryAddress::Relative'"); + } + + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'MemoryAddress' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'MemoryAddress' enum variant: " + tag); } } }; @@ -861,11 +1197,29 @@ struct HeapArray { { std::string name = "HeapArray"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "pointer", pointer, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "size", size, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "pointer", pointer); + break; + case 1: + Helpers::convert_or_throw(val, name, "size", size); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for HeapArray: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "pointer", pointer, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "size", size, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "pointer", pointer, 0); Helpers::conv_fld_from_array(array, name, "size", size, 1); } else { @@ -897,13 +1251,37 @@ struct BlackBoxOp { { std::string name = "AES128Encrypt"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "iv", iv, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "key", key, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 1: + Helpers::convert_or_throw(val, name, "iv", iv); + break; + case 2: + Helpers::convert_or_throw(val, name, "key", key); + break; + case 3: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for AES128Encrypt: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "iv", iv, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "key", key, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "inputs", inputs, 0); Helpers::conv_fld_from_array(array, name, "iv", iv, 1); Helpers::conv_fld_from_array(array, name, "key", key, 2); @@ -931,11 +1309,29 @@ struct BlackBoxOp { { std::string name = "Blake2s"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "message", message, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "message", message); + break; + case 1: + Helpers::convert_or_throw(val, name, "output", output); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Blake2s: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "message", message, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "message", message, 0); Helpers::conv_fld_from_array(array, name, "output", output, 1); } else { @@ -961,11 +1357,29 @@ struct BlackBoxOp { { std::string name = "Blake3"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "message", message, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "message", message); + break; + case 1: + Helpers::convert_or_throw(val, name, "output", output); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Blake3: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "message", message, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "message", message, 0); Helpers::conv_fld_from_array(array, name, "output", output, 1); } else { @@ -991,11 +1405,29 @@ struct BlackBoxOp { { std::string name = "Keccakf1600"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "input", input); + break; + case 1: + Helpers::convert_or_throw(val, name, "output", output); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Keccakf1600: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "input", input, 0); Helpers::conv_fld_from_array(array, name, "output", output, 1); } else { @@ -1027,14 +1459,41 @@ struct BlackBoxOp { { std::string name = "EcdsaSecp256k1"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_msg", hashed_msg, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_x", public_key_x, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "result", result, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "hashed_msg", hashed_msg); + break; + case 1: + Helpers::convert_or_throw(val, name, "public_key_x", public_key_x); + break; + case 2: + Helpers::convert_or_throw(val, name, "public_key_y", public_key_y); + break; + case 3: + Helpers::convert_or_throw(val, name, "signature", signature); + break; + case 4: + Helpers::convert_or_throw(val, name, "result", result); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for EcdsaSecp256k1: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 5, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_msg", hashed_msg, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_x", public_key_x, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "result", result, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 5, 0); Helpers::conv_fld_from_array(array, name, "hashed_msg", hashed_msg, 0); Helpers::conv_fld_from_array(array, name, "public_key_x", public_key_x, 1); Helpers::conv_fld_from_array(array, name, "public_key_y", public_key_y, 2); @@ -1069,14 +1528,41 @@ struct BlackBoxOp { { std::string name = "EcdsaSecp256r1"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_msg", hashed_msg, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_x", public_key_x, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "result", result, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "hashed_msg", hashed_msg); + break; + case 1: + Helpers::convert_or_throw(val, name, "public_key_x", public_key_x); + break; + case 2: + Helpers::convert_or_throw(val, name, "public_key_y", public_key_y); + break; + case 3: + Helpers::convert_or_throw(val, name, "signature", signature); + break; + case 4: + Helpers::convert_or_throw(val, name, "result", result); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for EcdsaSecp256r1: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 5, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_msg", hashed_msg, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_x", public_key_x, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "result", result, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 5, 0); Helpers::conv_fld_from_array(array, name, "hashed_msg", hashed_msg, 0); Helpers::conv_fld_from_array(array, name, "public_key_x", public_key_x, 1); Helpers::conv_fld_from_array(array, name, "public_key_y", public_key_y, 2); @@ -1107,12 +1593,33 @@ struct BlackBoxOp { { std::string name = "MultiScalarMul"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "points", points, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "scalars", scalars, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "points", points); + break; + case 1: + Helpers::convert_or_throw(val, name, "scalars", scalars); + break; + case 2: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for MultiScalarMul: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "points", points, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "scalars", scalars, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "points", points, 0); Helpers::conv_fld_from_array(array, name, "scalars", scalars, 1); Helpers::conv_fld_from_array(array, name, "outputs", outputs, 2); @@ -1145,14 +1652,41 @@ struct BlackBoxOp { { std::string name = "EmbeddedCurveAdd"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "input1_x", input1_x, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "input1_y", input1_y, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "input2_x", input2_x, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "input2_y", input2_y, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "result", result, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "input1_x", input1_x); + break; + case 1: + Helpers::convert_or_throw(val, name, "input1_y", input1_y); + break; + case 2: + Helpers::convert_or_throw(val, name, "input2_x", input2_x); + break; + case 3: + Helpers::convert_or_throw(val, name, "input2_y", input2_y); + break; + case 4: + Helpers::convert_or_throw(val, name, "result", result); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for EmbeddedCurveAdd: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 5, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "input1_x", input1_x, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "input1_y", input1_y, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "input2_x", input2_x, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "input2_y", input2_y, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "result", result, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 5, 0); Helpers::conv_fld_from_array(array, name, "input1_x", input1_x, 0); Helpers::conv_fld_from_array(array, name, "input1_y", input1_y, 1); Helpers::conv_fld_from_array(array, name, "input2_x", input2_x, 2); @@ -1181,11 +1715,29 @@ struct BlackBoxOp { { std::string name = "Poseidon2Permutation"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "message", message, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "message", message); + break; + case 1: + Helpers::convert_or_throw(val, name, "output", output); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Poseidon2Permutation: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "message", message, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "message", message, 0); Helpers::conv_fld_from_array(array, name, "output", output, 1); } else { @@ -1213,12 +1765,33 @@ struct BlackBoxOp { { std::string name = "Sha256Compression"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "hash_values", hash_values, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "input", input); + break; + case 1: + Helpers::convert_or_throw(val, name, "hash_values", hash_values); + break; + case 2: + Helpers::convert_or_throw(val, name, "output", output); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Sha256Compression: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "hash_values", hash_values, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "input", input, 0); Helpers::conv_fld_from_array(array, name, "hash_values", hash_values, 1); Helpers::conv_fld_from_array(array, name, "output", output, 2); @@ -1251,14 +1824,41 @@ struct BlackBoxOp { { std::string name = "ToRadix"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "radix", radix, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output_pointer", output_pointer, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "num_limbs", num_limbs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output_bits", output_bits, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "input", input); + break; + case 1: + Helpers::convert_or_throw(val, name, "radix", radix); + break; + case 2: + Helpers::convert_or_throw(val, name, "output_pointer", output_pointer); + break; + case 3: + Helpers::convert_or_throw(val, name, "num_limbs", num_limbs); + break; + case 4: + Helpers::convert_or_throw(val, name, "output_bits", output_bits); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for ToRadix: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 5, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "radix", radix, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output_pointer", output_pointer, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "num_limbs", num_limbs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output_bits", output_bits, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 5, 0); Helpers::conv_fld_from_array(array, name, "input", input, 0); Helpers::conv_fld_from_array(array, name, "radix", radix, 1); Helpers::conv_fld_from_array(array, name, "output_pointer", output_pointer, 2); @@ -1361,130 +1961,269 @@ struct BlackBoxOp { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'BlackBoxOp'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'BlackBoxOp'"); - } - if (tag == "AES128Encrypt") { - AES128Encrypt v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::AES128Encrypt'"); - } - - value = v; - } else if (tag == "Blake2s") { - Blake2s v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::Blake2s'"); - } - - value = v; - } else if (tag == "Blake3") { - Blake3 v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::Blake3'"); - } - - value = v; - } else if (tag == "Keccakf1600") { - Keccakf1600 v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::Keccakf1600'"); - } - - value = v; - } else if (tag == "EcdsaSecp256k1") { - EcdsaSecp256k1 v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::EcdsaSecp256k1'"); - } - - value = v; - } else if (tag == "EcdsaSecp256r1") { - EcdsaSecp256r1 v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::EcdsaSecp256r1'"); - } - - value = v; - } else if (tag == "MultiScalarMul") { - MultiScalarMul v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::MultiScalarMul'"); - } - - value = v; - } else if (tag == "EmbeddedCurveAdd") { - EmbeddedCurveAdd v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::EmbeddedCurveAdd'"); - } - - value = v; - } else if (tag == "Poseidon2Permutation") { - Poseidon2Permutation v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("expected u8 variant tag for enum 'BlackBoxOp'"); + } + switch (tag) { + case 0: { + AES128Encrypt v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::AES128Encrypt'"); + } + value = v; + break; + } + case 1: { + Blake2s v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Blake2s'"); + } + value = v; + break; + } + case 2: { + Blake3 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Blake3'"); + } + value = v; + break; + } + case 3: { + Keccakf1600 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Keccakf1600'"); + } + value = v; + break; + } + case 4: { + EcdsaSecp256k1 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::EcdsaSecp256k1'"); + } + value = v; + break; + } + case 5: { + EcdsaSecp256r1 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::EcdsaSecp256r1'"); + } + value = v; + break; + } + case 6: { + MultiScalarMul v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::MultiScalarMul'"); + } + value = v; + break; + } + case 7: { + EmbeddedCurveAdd v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::EmbeddedCurveAdd'"); + } + value = v; + break; + } + case 8: { + Poseidon2Permutation v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Poseidon2Permutation'"); + } + value = v; + break; + } + case 9: { + Sha256Compression v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Sha256Compression'"); + } + value = v; + break; + } + case 10: { + ToRadix v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::ToRadix'"); + } + value = v; + break; + } + default: std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::Poseidon2Permutation'"); + throw_or_abort("unknown 'BlackBoxOp' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "Sha256Compression") { - Sha256Compression v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::Sha256Compression'"); - } - - value = v; - } else if (tag == "ToRadix") { - ToRadix v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("error converting tag to string for enum 'BlackBoxOp'"); + } + if (tag == "AES128Encrypt") { + AES128Encrypt v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::AES128Encrypt'"); + } + + value = v; + } else if (tag == "Blake2s") { + Blake2s v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Blake2s'"); + } + + value = v; + } else if (tag == "Blake3") { + Blake3 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Blake3'"); + } + + value = v; + } else if (tag == "Keccakf1600") { + Keccakf1600 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Keccakf1600'"); + } + + value = v; + } else if (tag == "EcdsaSecp256k1") { + EcdsaSecp256k1 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::EcdsaSecp256k1'"); + } + + value = v; + } else if (tag == "EcdsaSecp256r1") { + EcdsaSecp256r1 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::EcdsaSecp256r1'"); + } + + value = v; + } else if (tag == "MultiScalarMul") { + MultiScalarMul v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::MultiScalarMul'"); + } + + value = v; + } else if (tag == "EmbeddedCurveAdd") { + EmbeddedCurveAdd v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::EmbeddedCurveAdd'"); + } + + value = v; + } else if (tag == "Poseidon2Permutation") { + Poseidon2Permutation v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Poseidon2Permutation'"); + } + + value = v; + } else if (tag == "Sha256Compression") { + Sha256Compression v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::Sha256Compression'"); + } + + value = v; + } else if (tag == "ToRadix") { + ToRadix v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxOp::ToRadix'"); + } + + value = v; + } else { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::ToRadix'"); + throw_or_abort("unknown 'BlackBoxOp' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'BlackBoxOp' enum variant: " + tag); } } }; @@ -1546,11 +2285,29 @@ struct HeapValueType { { std::string name = "Array"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "value_types", value_types, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "size", size, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "value_types", value_types); + break; + case 1: + Helpers::convert_or_throw(val, name, "size", size); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Array: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "value_types", value_types, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "size", size, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "value_types", value_types, 0); Helpers::conv_fld_from_array(array, name, "size", size, 1); } else { @@ -1574,10 +2331,25 @@ struct HeapValueType { { std::string name = "Vector"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "value_types", value_types, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "value_types", value_types); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Vector: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 1, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "value_types", value_types, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 1, 0); Helpers::conv_fld_from_array(array, name, "value_types", value_types, 0); } else { throw_or_abort("expected MAP or ARRAY for " + name); @@ -1633,50 +2405,101 @@ struct HeapValueType { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'HeapValueType'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'HeapValueType'"); - } - if (tag == "Simple") { - Simple v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'HeapValueType::Simple'"); - } - - value = v; - } else if (tag == "Array") { - Array v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("expected u8 variant tag for enum 'HeapValueType'"); + } + switch (tag) { + case 0: { + Simple v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'HeapValueType::Simple'"); + } + value = v; + break; + } + case 1: { + Array v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'HeapValueType::Array'"); + } + value = v; + break; + } + case 2: { + Vector v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'HeapValueType::Vector'"); + } + value = v; + break; + } + default: std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'HeapValueType::Array'"); + throw_or_abort("unknown 'HeapValueType' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "Vector") { - Vector v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'HeapValueType::Vector'"); + throw_or_abort("error converting tag to string for enum 'HeapValueType'"); + } + if (tag == "Simple") { + Simple v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'HeapValueType::Simple'"); + } + + value = v; + } else if (tag == "Array") { + Array v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'HeapValueType::Array'"); + } + + value = v; + } else if (tag == "Vector") { + Vector v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'HeapValueType::Vector'"); + } + + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'HeapValueType' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'HeapValueType' enum variant: " + tag); } } }; @@ -1698,11 +2521,29 @@ struct HeapVector { { std::string name = "HeapVector"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "pointer", pointer, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "size", size, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "pointer", pointer); + break; + case 1: + Helpers::convert_or_throw(val, name, "size", size); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for HeapVector: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "pointer", pointer, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "size", size, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "pointer", pointer, 0); Helpers::conv_fld_from_array(array, name, "size", size, 1); } else { @@ -1815,50 +2656,101 @@ struct ValueOrArray { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'ValueOrArray'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'ValueOrArray'"); - } - if (tag == "MemoryAddress") { - MemoryAddress v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'ValueOrArray::MemoryAddress'"); - } - - value = v; - } else if (tag == "HeapArray") { - HeapArray v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("expected u8 variant tag for enum 'ValueOrArray'"); + } + switch (tag) { + case 0: { + MemoryAddress v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ValueOrArray::MemoryAddress'"); + } + value = v; + break; + } + case 1: { + HeapArray v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ValueOrArray::HeapArray'"); + } + value = v; + break; + } + case 2: { + HeapVector v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ValueOrArray::HeapVector'"); + } + value = v; + break; + } + default: std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'ValueOrArray::HeapArray'"); + throw_or_abort("unknown 'ValueOrArray' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "HeapVector") { - HeapVector v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'ValueOrArray::HeapVector'"); + throw_or_abort("error converting tag to string for enum 'ValueOrArray'"); + } + if (tag == "MemoryAddress") { + MemoryAddress v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ValueOrArray::MemoryAddress'"); + } + + value = v; + } else if (tag == "HeapArray") { + HeapArray v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ValueOrArray::HeapArray'"); + } + + value = v; + } else if (tag == "HeapVector") { + HeapVector v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ValueOrArray::HeapVector'"); + } + + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'ValueOrArray' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'ValueOrArray' enum variant: " + tag); } } }; @@ -1886,13 +2778,37 @@ struct BrilligOpcode { { std::string name = "BinaryFieldOp"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "op", op, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination", destination); + break; + case 1: + Helpers::convert_or_throw(val, name, "op", op); + break; + case 2: + Helpers::convert_or_throw(val, name, "lhs", lhs); + break; + case 3: + Helpers::convert_or_throw(val, name, "rhs", rhs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for BinaryFieldOp: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "op", op, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "destination", destination, 0); Helpers::conv_fld_from_array(array, name, "op", op, 1); Helpers::conv_fld_from_array(array, name, "lhs", lhs, 2); @@ -1926,14 +2842,41 @@ struct BrilligOpcode { { std::string name = "BinaryIntOp"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "op", op, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination", destination); + break; + case 1: + Helpers::convert_or_throw(val, name, "op", op); + break; + case 2: + Helpers::convert_or_throw(val, name, "bit_size", bit_size); + break; + case 3: + Helpers::convert_or_throw(val, name, "lhs", lhs); + break; + case 4: + Helpers::convert_or_throw(val, name, "rhs", rhs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for BinaryIntOp: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 5, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "op", op, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 5, 0); Helpers::conv_fld_from_array(array, name, "destination", destination, 0); Helpers::conv_fld_from_array(array, name, "op", op, 1); Helpers::conv_fld_from_array(array, name, "bit_size", bit_size, 2); @@ -1964,12 +2907,33 @@ struct BrilligOpcode { { std::string name = "Not"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "source", source, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination", destination); + break; + case 1: + Helpers::convert_or_throw(val, name, "source", source); + break; + case 2: + Helpers::convert_or_throw(val, name, "bit_size", bit_size); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Not: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "source", source, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "destination", destination, 0); Helpers::conv_fld_from_array(array, name, "source", source, 1); Helpers::conv_fld_from_array(array, name, "bit_size", bit_size, 2); @@ -1998,12 +2962,33 @@ struct BrilligOpcode { { std::string name = "Cast"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "source", source, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination", destination); + break; + case 1: + Helpers::convert_or_throw(val, name, "source", source); + break; + case 2: + Helpers::convert_or_throw(val, name, "bit_size", bit_size); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Cast: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "source", source, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "destination", destination, 0); Helpers::conv_fld_from_array(array, name, "source", source, 1); Helpers::conv_fld_from_array(array, name, "bit_size", bit_size, 2); @@ -2030,11 +3015,29 @@ struct BrilligOpcode { { std::string name = "JumpIf"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "condition", condition, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "location", location, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "condition", condition); + break; + case 1: + Helpers::convert_or_throw(val, name, "location", location); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for JumpIf: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "condition", condition, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "location", location, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "condition", condition, 0); Helpers::conv_fld_from_array(array, name, "location", location, 1); } else { @@ -2058,10 +3061,25 @@ struct BrilligOpcode { { std::string name = "Jump"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "location", location, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "location", location); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Jump: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 1, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "location", location, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 1, 0); Helpers::conv_fld_from_array(array, name, "location", location, 0); } else { throw_or_abort("expected MAP or ARRAY for " + name); @@ -2088,12 +3106,33 @@ struct BrilligOpcode { { std::string name = "CalldataCopy"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination_address", destination_address, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "size_address", size_address, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "offset_address", offset_address, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination_address", destination_address); + break; + case 1: + Helpers::convert_or_throw(val, name, "size_address", size_address); + break; + case 2: + Helpers::convert_or_throw(val, name, "offset_address", offset_address); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for CalldataCopy: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination_address", destination_address, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "size_address", size_address, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "offset_address", offset_address, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "destination_address", destination_address, 0); Helpers::conv_fld_from_array(array, name, "size_address", size_address, 1); Helpers::conv_fld_from_array(array, name, "offset_address", offset_address, 2); @@ -2118,10 +3157,25 @@ struct BrilligOpcode { { std::string name = "Call"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "location", location, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "location", location); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Call: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 1, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "location", location, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 1, 0); Helpers::conv_fld_from_array(array, name, "location", location, 0); } else { throw_or_abort("expected MAP or ARRAY for " + name); @@ -2148,12 +3202,33 @@ struct BrilligOpcode { { std::string name = "Const"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "value", value, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination", destination); + break; + case 1: + Helpers::convert_or_throw(val, name, "bit_size", bit_size); + break; + case 2: + Helpers::convert_or_throw(val, name, "value", value); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Const: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "value", value, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "destination", destination, 0); Helpers::conv_fld_from_array(array, name, "bit_size", bit_size, 1); Helpers::conv_fld_from_array(array, name, "value", value, 2); @@ -2182,12 +3257,33 @@ struct BrilligOpcode { { std::string name = "IndirectConst"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination_pointer", destination_pointer, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "value", value, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination_pointer", destination_pointer); + break; + case 1: + Helpers::convert_or_throw(val, name, "bit_size", bit_size); + break; + case 2: + Helpers::convert_or_throw(val, name, "value", value); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for IndirectConst: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination_pointer", destination_pointer, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "bit_size", bit_size, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "value", value, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "destination_pointer", destination_pointer, 0); Helpers::conv_fld_from_array(array, name, "bit_size", bit_size, 1); Helpers::conv_fld_from_array(array, name, "value", value, 2); @@ -2227,14 +3323,42 @@ struct BrilligOpcode { { std::string name = "ForeignCall"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "function", function, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "destinations", destinations, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination_value_types", destination_value_types, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "input_value_types", input_value_types, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "function", function); + break; + case 1: + Helpers::convert_or_throw(val, name, "destinations", destinations); + break; + case 2: + Helpers::convert_or_throw(val, name, "destination_value_types", destination_value_types); + break; + case 3: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 4: + Helpers::convert_or_throw(val, name, "input_value_types", input_value_types); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for ForeignCall: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 5, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "function", function, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "destinations", destinations, false); + Helpers::conv_fld_from_kvmap( + kvmap, name, "destination_value_types", destination_value_types, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "input_value_types", input_value_types, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 5, 0); Helpers::conv_fld_from_array(array, name, "function", function, 0); Helpers::conv_fld_from_array(array, name, "destinations", destinations, 1); Helpers::conv_fld_from_array(array, name, "destination_value_types", destination_value_types, 2); @@ -2263,11 +3387,29 @@ struct BrilligOpcode { { std::string name = "Mov"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "source", source, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination", destination); + break; + case 1: + Helpers::convert_or_throw(val, name, "source", source); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Mov: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "source", source, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "destination", destination, 0); Helpers::conv_fld_from_array(array, name, "source", source, 1); } else { @@ -2297,13 +3439,37 @@ struct BrilligOpcode { { std::string name = "ConditionalMov"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "source_a", source_a, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "source_b", source_b, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "condition", condition, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination", destination); + break; + case 1: + Helpers::convert_or_throw(val, name, "source_a", source_a); + break; + case 2: + Helpers::convert_or_throw(val, name, "source_b", source_b); + break; + case 3: + Helpers::convert_or_throw(val, name, "condition", condition); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for ConditionalMov: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "source_a", source_a, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "source_b", source_b, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "condition", condition, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "destination", destination, 0); Helpers::conv_fld_from_array(array, name, "source_a", source_a, 1); Helpers::conv_fld_from_array(array, name, "source_b", source_b, 2); @@ -2331,11 +3497,29 @@ struct BrilligOpcode { { std::string name = "Load"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "source_pointer", source_pointer, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination", destination); + break; + case 1: + Helpers::convert_or_throw(val, name, "source_pointer", source_pointer); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Load: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination", destination, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "source_pointer", source_pointer, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "destination", destination, 0); Helpers::conv_fld_from_array(array, name, "source_pointer", source_pointer, 1); } else { @@ -2361,11 +3545,29 @@ struct BrilligOpcode { { std::string name = "Store"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "destination_pointer", destination_pointer, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "source", source, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "destination_pointer", destination_pointer); + break; + case 1: + Helpers::convert_or_throw(val, name, "source", source); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Store: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "destination_pointer", destination_pointer, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "source", source, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "destination_pointer", destination_pointer, 0); Helpers::conv_fld_from_array(array, name, "source", source, 1); } else { @@ -2407,10 +3609,25 @@ struct BrilligOpcode { { std::string name = "Trap"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "revert_data", revert_data, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "revert_data", revert_data); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Trap: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 1, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "revert_data", revert_data, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 1, 0); Helpers::conv_fld_from_array(array, name, "revert_data", revert_data, 0); } else { throw_or_abort("expected MAP or ARRAY for " + name); @@ -2433,10 +3650,25 @@ struct BrilligOpcode { { std::string name = "Stop"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "return_data", return_data, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "return_data", return_data); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Stop: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 1, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "return_data", return_data, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 1, 0); Helpers::conv_fld_from_array(array, name, "return_data", return_data, 0); } else { throw_or_abort("expected MAP or ARRAY for " + name); @@ -2575,203 +3807,424 @@ struct BrilligOpcode { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'BrilligOpcode'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'BrilligOpcode'"); - } - if (tag == "BinaryFieldOp") { - BinaryFieldOp v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::BinaryFieldOp'"); - } - - value = v; - } else if (tag == "BinaryIntOp") { - BinaryIntOp v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("expected u8 variant tag for enum 'BrilligOpcode'"); + } + switch (tag) { + case 0: { + BinaryFieldOp v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::BinaryFieldOp'"); + } + value = v; + break; + } + case 1: { + BinaryIntOp v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::BinaryIntOp'"); + } + value = v; + break; + } + case 2: { + Not v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Not'"); + } + value = v; + break; + } + case 3: { + Cast v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Cast'"); + } + value = v; + break; + } + case 4: { + JumpIf v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::JumpIf'"); + } + value = v; + break; + } + case 5: { + Jump v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Jump'"); + } + value = v; + break; + } + case 6: { + CalldataCopy v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::CalldataCopy'"); + } + value = v; + break; + } + case 7: { + Call v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Call'"); + } + value = v; + break; + } + case 8: { + Const v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Const'"); + } + value = v; + break; + } + case 9: { + IndirectConst v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::IndirectConst'"); + } + value = v; + break; + } + case 10: { + Return v; + value = v; + break; + } + case 11: { + ForeignCall v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::ForeignCall'"); + } + value = v; + break; + } + case 12: { + Mov v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Mov'"); + } + value = v; + break; + } + case 13: { + ConditionalMov v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::ConditionalMov'"); + } + value = v; + break; + } + case 14: { + Load v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Load'"); + } + value = v; + break; + } + case 15: { + Store v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Store'"); + } + value = v; + break; + } + case 16: { + BlackBox v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::BlackBox'"); + } + value = v; + break; + } + case 17: { + Trap v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Trap'"); + } + value = v; + break; + } + case 18: { + Stop v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Stop'"); + } + value = v; + break; + } + default: std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::BinaryIntOp'"); + throw_or_abort("unknown 'BrilligOpcode' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "Not") { - Not v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Not'"); - } - - value = v; - } else if (tag == "Cast") { - Cast v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Cast'"); - } - - value = v; - } else if (tag == "JumpIf") { - JumpIf v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::JumpIf'"); - } - - value = v; - } else if (tag == "Jump") { - Jump v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Jump'"); - } - - value = v; - } else if (tag == "CalldataCopy") { - CalldataCopy v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::CalldataCopy'"); - } - - value = v; - } else if (tag == "Call") { - Call v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Call'"); - } - - value = v; - } else if (tag == "Const") { - Const v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Const'"); - } - - value = v; - } else if (tag == "IndirectConst") { - IndirectConst v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::IndirectConst'"); - } - - value = v; - } else if (tag == "Return") { - Return v; - value = v; - } else if (tag == "ForeignCall") { - ForeignCall v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::ForeignCall'"); - } - - value = v; - } else if (tag == "Mov") { - Mov v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Mov'"); - } - - value = v; - } else if (tag == "ConditionalMov") { - ConditionalMov v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::ConditionalMov'"); - } - - value = v; - } else if (tag == "Load") { - Load v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Load'"); - } - - value = v; - } else if (tag == "Store") { - Store v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Store'"); - } - - value = v; - } else if (tag == "BlackBox") { - BlackBox v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::BlackBox'"); - } - - value = v; - } else if (tag == "Trap") { - Trap v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Trap'"); - } - - value = v; - } else if (tag == "Stop") { - Stop v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("error converting tag to string for enum 'BrilligOpcode'"); + } + if (tag == "BinaryFieldOp") { + BinaryFieldOp v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::BinaryFieldOp'"); + } + + value = v; + } else if (tag == "BinaryIntOp") { + BinaryIntOp v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::BinaryIntOp'"); + } + + value = v; + } else if (tag == "Not") { + Not v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Not'"); + } + + value = v; + } else if (tag == "Cast") { + Cast v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Cast'"); + } + + value = v; + } else if (tag == "JumpIf") { + JumpIf v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::JumpIf'"); + } + + value = v; + } else if (tag == "Jump") { + Jump v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Jump'"); + } + + value = v; + } else if (tag == "CalldataCopy") { + CalldataCopy v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::CalldataCopy'"); + } + + value = v; + } else if (tag == "Call") { + Call v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Call'"); + } + + value = v; + } else if (tag == "Const") { + Const v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Const'"); + } + + value = v; + } else if (tag == "IndirectConst") { + IndirectConst v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::IndirectConst'"); + } + + value = v; + } else if (tag == "Return") { + Return v; + value = v; + } else if (tag == "ForeignCall") { + ForeignCall v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::ForeignCall'"); + } + + value = v; + } else if (tag == "Mov") { + Mov v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Mov'"); + } + + value = v; + } else if (tag == "ConditionalMov") { + ConditionalMov v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::ConditionalMov'"); + } + + value = v; + } else if (tag == "Load") { + Load v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Load'"); + } + + value = v; + } else if (tag == "Store") { + Store v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Store'"); + } + + value = v; + } else if (tag == "BlackBox") { + BlackBox v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::BlackBox'"); + } + + value = v; + } else if (tag == "Trap") { + Trap v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Trap'"); + } + + value = v; + } else if (tag == "Stop") { + Stop v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOpcode::Stop'"); + } + + value = v; + } else { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::Stop'"); + throw_or_abort("unknown 'BrilligOpcode' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'BrilligOpcode' enum variant: " + tag); } } }; @@ -2876,40 +4329,80 @@ struct FunctionInput { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'FunctionInput'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'FunctionInput'"); - } - if (tag == "Constant") { - Constant v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'FunctionInput::Constant'"); + throw_or_abort("expected u8 variant tag for enum 'FunctionInput'"); + } + switch (tag) { + case 0: { + Constant v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'FunctionInput::Constant'"); + } + value = v; + break; + } + case 1: { + Witness v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'FunctionInput::Witness'"); + } + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'FunctionInput' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "Witness") { - Witness v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'FunctionInput::Witness'"); + throw_or_abort("error converting tag to string for enum 'FunctionInput'"); + } + if (tag == "Constant") { + Constant v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'FunctionInput::Constant'"); + } + + value = v; + } else if (tag == "Witness") { + Witness v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'FunctionInput::Witness'"); + } + + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'FunctionInput' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'FunctionInput' enum variant: " + tag); } } }; @@ -2937,13 +4430,37 @@ struct BlackBoxFuncCall { { std::string name = "AES128Encrypt"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "iv", iv, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "key", key, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 1: + Helpers::convert_or_throw(val, name, "iv", iv); + break; + case 2: + Helpers::convert_or_throw(val, name, "key", key); + break; + case 3: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for AES128Encrypt: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "iv", iv, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "key", key, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "inputs", inputs, 0); Helpers::conv_fld_from_array(array, name, "iv", iv, 1); Helpers::conv_fld_from_array(array, name, "key", key, 2); @@ -2975,13 +4492,37 @@ struct BlackBoxFuncCall { { std::string name = "AND"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "lhs", lhs); + break; + case 1: + Helpers::convert_or_throw(val, name, "rhs", rhs); + break; + case 2: + Helpers::convert_or_throw(val, name, "num_bits", num_bits); + break; + case 3: + Helpers::convert_or_throw(val, name, "output", output); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for AND: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "lhs", lhs, 0); Helpers::conv_fld_from_array(array, name, "rhs", rhs, 1); Helpers::conv_fld_from_array(array, name, "num_bits", num_bits, 2); @@ -3013,13 +4554,37 @@ struct BlackBoxFuncCall { { std::string name = "XOR"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "lhs", lhs); + break; + case 1: + Helpers::convert_or_throw(val, name, "rhs", rhs); + break; + case 2: + Helpers::convert_or_throw(val, name, "num_bits", num_bits); + break; + case 3: + Helpers::convert_or_throw(val, name, "output", output); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for XOR: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "lhs", lhs, 0); Helpers::conv_fld_from_array(array, name, "rhs", rhs, 1); Helpers::conv_fld_from_array(array, name, "num_bits", num_bits, 2); @@ -3047,11 +4612,29 @@ struct BlackBoxFuncCall { { std::string name = "RANGE"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "input", input); + break; + case 1: + Helpers::convert_or_throw(val, name, "num_bits", num_bits); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for RANGE: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "input", input, 0); Helpers::conv_fld_from_array(array, name, "num_bits", num_bits, 1); } else { @@ -3077,11 +4660,29 @@ struct BlackBoxFuncCall { { std::string name = "Blake2s"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 1: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Blake2s: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "inputs", inputs, 0); Helpers::conv_fld_from_array(array, name, "outputs", outputs, 1); } else { @@ -3107,11 +4708,29 @@ struct BlackBoxFuncCall { { std::string name = "Blake3"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 1: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Blake3: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "inputs", inputs, 0); Helpers::conv_fld_from_array(array, name, "outputs", outputs, 1); } else { @@ -3145,15 +4764,45 @@ struct BlackBoxFuncCall { { std::string name = "EcdsaSecp256k1"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_x", public_key_x, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_message", hashed_message, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "public_key_x", public_key_x); + break; + case 1: + Helpers::convert_or_throw(val, name, "public_key_y", public_key_y); + break; + case 2: + Helpers::convert_or_throw(val, name, "signature", signature); + break; + case 3: + Helpers::convert_or_throw(val, name, "hashed_message", hashed_message); + break; + case 4: + Helpers::convert_or_throw(val, name, "predicate", predicate); + break; + case 5: + Helpers::convert_or_throw(val, name, "output", output); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for EcdsaSecp256k1: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 6, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_x", public_key_x, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_message", hashed_message, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 6, 0); Helpers::conv_fld_from_array(array, name, "public_key_x", public_key_x, 0); Helpers::conv_fld_from_array(array, name, "public_key_y", public_key_y, 1); Helpers::conv_fld_from_array(array, name, "signature", signature, 2); @@ -3191,15 +4840,45 @@ struct BlackBoxFuncCall { { std::string name = "EcdsaSecp256r1"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_x", public_key_x, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_message", hashed_message, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "public_key_x", public_key_x); + break; + case 1: + Helpers::convert_or_throw(val, name, "public_key_y", public_key_y); + break; + case 2: + Helpers::convert_or_throw(val, name, "signature", signature); + break; + case 3: + Helpers::convert_or_throw(val, name, "hashed_message", hashed_message); + break; + case 4: + Helpers::convert_or_throw(val, name, "predicate", predicate); + break; + case 5: + Helpers::convert_or_throw(val, name, "output", output); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for EcdsaSecp256r1: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 6, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_x", public_key_x, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_message", hashed_message, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 6, 0); Helpers::conv_fld_from_array(array, name, "public_key_x", public_key_x, 0); Helpers::conv_fld_from_array(array, name, "public_key_y", public_key_y, 1); Helpers::conv_fld_from_array(array, name, "signature", signature, 2); @@ -3233,13 +4912,37 @@ struct BlackBoxFuncCall { { std::string name = "MultiScalarMul"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "points", points, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "scalars", scalars, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "points", points); + break; + case 1: + Helpers::convert_or_throw(val, name, "scalars", scalars); + break; + case 2: + Helpers::convert_or_throw(val, name, "predicate", predicate); + break; + case 3: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for MultiScalarMul: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "points", points, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "scalars", scalars, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "points", points, 0); Helpers::conv_fld_from_array(array, name, "scalars", scalars, 1); Helpers::conv_fld_from_array(array, name, "predicate", predicate, 2); @@ -3271,13 +4974,37 @@ struct BlackBoxFuncCall { { std::string name = "EmbeddedCurveAdd"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "input1", input1, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "input2", input2, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "input1", input1); + break; + case 1: + Helpers::convert_or_throw(val, name, "input2", input2); + break; + case 2: + Helpers::convert_or_throw(val, name, "predicate", predicate); + break; + case 3: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for EmbeddedCurveAdd: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "input1", input1, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "input2", input2, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "input1", input1, 0); Helpers::conv_fld_from_array(array, name, "input2", input2, 1); Helpers::conv_fld_from_array(array, name, "predicate", predicate, 2); @@ -3305,11 +5032,29 @@ struct BlackBoxFuncCall { { std::string name = "Keccakf1600"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 1: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Keccakf1600: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "inputs", inputs, 0); Helpers::conv_fld_from_array(array, name, "outputs", outputs, 1); } else { @@ -3343,15 +5088,45 @@ struct BlackBoxFuncCall { { std::string name = "RecursiveAggregation"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "verification_key", verification_key, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "proof", proof, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_inputs", public_inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "key_hash", key_hash, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "proof_type", proof_type, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "verification_key", verification_key); + break; + case 1: + Helpers::convert_or_throw(val, name, "proof", proof); + break; + case 2: + Helpers::convert_or_throw(val, name, "public_inputs", public_inputs); + break; + case 3: + Helpers::convert_or_throw(val, name, "key_hash", key_hash); + break; + case 4: + Helpers::convert_or_throw(val, name, "proof_type", proof_type); + break; + case 5: + Helpers::convert_or_throw(val, name, "predicate", predicate); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for RecursiveAggregation: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 6, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "verification_key", verification_key, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "proof", proof, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_inputs", public_inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "key_hash", key_hash, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "proof_type", proof_type, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 6, 0); Helpers::conv_fld_from_array(array, name, "verification_key", verification_key, 0); Helpers::conv_fld_from_array(array, name, "proof", proof, 1); Helpers::conv_fld_from_array(array, name, "public_inputs", public_inputs, 2); @@ -3381,11 +5156,29 @@ struct BlackBoxFuncCall { { std::string name = "Poseidon2Permutation"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 1: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Poseidon2Permutation: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "inputs", inputs, 0); Helpers::conv_fld_from_array(array, name, "outputs", outputs, 1); } else { @@ -3413,12 +5206,33 @@ struct BlackBoxFuncCall { { std::string name = "Sha256Compression"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "hash_values", hash_values, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 1: + Helpers::convert_or_throw(val, name, "hash_values", hash_values); + break; + case 2: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Sha256Compression: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "hash_values", hash_values, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "inputs", inputs, 0); Helpers::conv_fld_from_array(array, name, "hash_values", hash_values, 1); Helpers::conv_fld_from_array(array, name, "outputs", outputs, 2); @@ -3534,160 +5348,332 @@ struct BlackBoxFuncCall { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'BlackBoxFuncCall'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'BlackBoxFuncCall'"); - } - if (tag == "AES128Encrypt") { - AES128Encrypt v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::AES128Encrypt'"); - } - - value = v; - } else if (tag == "AND") { - AND v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::AND'"); - } - - value = v; - } else if (tag == "XOR") { - XOR v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::XOR'"); - } - - value = v; - } else if (tag == "RANGE") { - RANGE v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::RANGE'"); - } - - value = v; - } else if (tag == "Blake2s") { - Blake2s v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Blake2s'"); - } - - value = v; - } else if (tag == "Blake3") { - Blake3 v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Blake3'"); - } - - value = v; - } else if (tag == "EcdsaSecp256k1") { - EcdsaSecp256k1 v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::EcdsaSecp256k1'"); - } - - value = v; - } else if (tag == "EcdsaSecp256r1") { - EcdsaSecp256r1 v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::EcdsaSecp256r1'"); - } - - value = v; - } else if (tag == "MultiScalarMul") { - MultiScalarMul v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::MultiScalarMul'"); - } - - value = v; - } else if (tag == "EmbeddedCurveAdd") { - EmbeddedCurveAdd v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::EmbeddedCurveAdd'"); - } - - value = v; - } else if (tag == "Keccakf1600") { - Keccakf1600 v; - try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Keccakf1600'"); - } - - value = v; - } else if (tag == "RecursiveAggregation") { - RecursiveAggregation v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("expected u8 variant tag for enum 'BlackBoxFuncCall'"); + } + switch (tag) { + case 0: { + AES128Encrypt v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::AES128Encrypt'"); + } + value = v; + break; + } + case 1: { + AND v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::AND'"); + } + value = v; + break; + } + case 2: { + XOR v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::XOR'"); + } + value = v; + break; + } + case 3: { + RANGE v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::RANGE'"); + } + value = v; + break; + } + case 4: { + Blake2s v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Blake2s'"); + } + value = v; + break; + } + case 5: { + Blake3 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Blake3'"); + } + value = v; + break; + } + case 6: { + EcdsaSecp256k1 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::EcdsaSecp256k1'"); + } + value = v; + break; + } + case 7: { + EcdsaSecp256r1 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::EcdsaSecp256r1'"); + } + value = v; + break; + } + case 8: { + MultiScalarMul v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::MultiScalarMul'"); + } + value = v; + break; + } + case 9: { + EmbeddedCurveAdd v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::EmbeddedCurveAdd'"); + } + value = v; + break; + } + case 10: { + Keccakf1600 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Keccakf1600'"); + } + value = v; + break; + } + case 11: { + RecursiveAggregation v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::RecursiveAggregation'"); + } + value = v; + break; + } + case 12: { + Poseidon2Permutation v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Poseidon2Permutation'"); + } + value = v; + break; + } + case 13: { + Sha256Compression v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Sha256Compression'"); + } + value = v; + break; + } + default: std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::RecursiveAggregation'"); + throw_or_abort("unknown 'BlackBoxFuncCall' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "Poseidon2Permutation") { - Poseidon2Permutation v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Poseidon2Permutation'"); - } - - value = v; - } else if (tag == "Sha256Compression") { - Sha256Compression v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("error converting tag to string for enum 'BlackBoxFuncCall'"); + } + if (tag == "AES128Encrypt") { + AES128Encrypt v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::AES128Encrypt'"); + } + + value = v; + } else if (tag == "AND") { + AND v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::AND'"); + } + + value = v; + } else if (tag == "XOR") { + XOR v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::XOR'"); + } + + value = v; + } else if (tag == "RANGE") { + RANGE v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::RANGE'"); + } + + value = v; + } else if (tag == "Blake2s") { + Blake2s v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Blake2s'"); + } + + value = v; + } else if (tag == "Blake3") { + Blake3 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Blake3'"); + } + + value = v; + } else if (tag == "EcdsaSecp256k1") { + EcdsaSecp256k1 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::EcdsaSecp256k1'"); + } + + value = v; + } else if (tag == "EcdsaSecp256r1") { + EcdsaSecp256r1 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::EcdsaSecp256r1'"); + } + + value = v; + } else if (tag == "MultiScalarMul") { + MultiScalarMul v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::MultiScalarMul'"); + } + + value = v; + } else if (tag == "EmbeddedCurveAdd") { + EmbeddedCurveAdd v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::EmbeddedCurveAdd'"); + } + + value = v; + } else if (tag == "Keccakf1600") { + Keccakf1600 v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Keccakf1600'"); + } + + value = v; + } else if (tag == "RecursiveAggregation") { + RecursiveAggregation v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::RecursiveAggregation'"); + } + + value = v; + } else if (tag == "Poseidon2Permutation") { + Poseidon2Permutation v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Poseidon2Permutation'"); + } + + value = v; + } else if (tag == "Sha256Compression") { + Sha256Compression v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Sha256Compression'"); + } + + value = v; + } else { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::Sha256Compression'"); + throw_or_abort("unknown 'BlackBoxFuncCall' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'BlackBoxFuncCall' enum variant: " + tag); } } }; @@ -3792,36 +5778,75 @@ struct BlockType { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'BlockType'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; + try { o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("expected u8 variant tag for enum 'BlockType'"); + } + switch (tag) { + case 0: { + Memory v; + value = v; + break; + } + case 1: { + CallData v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlockType::CallData'"); + } + value = v; + break; + } + case 2: { + ReturnData v; + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'BlockType' enum variant tag: " + std::to_string(tag)); } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'BlockType'"); - } - if (tag == "Memory") { - Memory v; - value = v; - } else if (tag == "CallData") { - CallData v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlockType::CallData'"); + throw_or_abort("error converting tag to string for enum 'BlockType'"); + } + if (tag == "Memory") { + Memory v; + value = v; + } else if (tag == "CallData") { + CallData v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BlockType::CallData'"); + } + + value = v; + } else if (tag == "ReturnData") { + ReturnData v; + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'BlockType' enum variant: " + tag); } - - value = v; - } else if (tag == "ReturnData") { - ReturnData v; - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'BlockType' enum variant: " + tag); } } }; @@ -3845,12 +5870,33 @@ struct Expression { { std::string name = "Expression"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "mul_terms", mul_terms, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "linear_combinations", linear_combinations, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "q_c", q_c, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "mul_terms", mul_terms); + break; + case 1: + Helpers::convert_or_throw(val, name, "linear_combinations", linear_combinations); + break; + case 2: + Helpers::convert_or_throw(val, name, "q_c", q_c); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Expression: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "mul_terms", mul_terms, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "linear_combinations", linear_combinations, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "q_c", q_c, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "mul_terms", mul_terms, 0); Helpers::conv_fld_from_array(array, name, "linear_combinations", linear_combinations, 1); Helpers::conv_fld_from_array(array, name, "q_c", q_c, 2); @@ -3964,50 +6010,101 @@ struct BrilligInputs { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'BrilligInputs'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'BrilligInputs'"); - } - if (tag == "Single") { - Single v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligInputs::Single'"); - } - - value = v; - } else if (tag == "Array") { - Array v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("expected u8 variant tag for enum 'BrilligInputs'"); + } + switch (tag) { + case 0: { + Single v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligInputs::Single'"); + } + value = v; + break; + } + case 1: { + Array v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligInputs::Array'"); + } + value = v; + break; + } + case 2: { + MemoryArray v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligInputs::MemoryArray'"); + } + value = v; + break; + } + default: std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligInputs::Array'"); + throw_or_abort("unknown 'BrilligInputs' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "MemoryArray") { - MemoryArray v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligInputs::MemoryArray'"); + throw_or_abort("error converting tag to string for enum 'BrilligInputs'"); + } + if (tag == "Single") { + Single v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligInputs::Single'"); + } + + value = v; + } else if (tag == "Array") { + Array v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligInputs::Array'"); + } + + value = v; + } else if (tag == "MemoryArray") { + MemoryArray v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligInputs::MemoryArray'"); + } + + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'BrilligInputs' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'BrilligInputs' enum variant: " + tag); } } }; @@ -4094,40 +6191,80 @@ struct BrilligOutputs { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'BrilligOutputs'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'BrilligOutputs'"); - } - if (tag == "Simple") { - Simple v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOutputs::Simple'"); + throw_or_abort("expected u8 variant tag for enum 'BrilligOutputs'"); + } + switch (tag) { + case 0: { + Simple v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOutputs::Simple'"); + } + value = v; + break; + } + case 1: { + Array v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOutputs::Array'"); + } + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'BrilligOutputs' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "Array") { - Array v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOutputs::Array'"); + throw_or_abort("error converting tag to string for enum 'BrilligOutputs'"); + } + if (tag == "Simple") { + Simple v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOutputs::Simple'"); + } + + value = v; + } else if (tag == "Array") { + Array v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'BrilligOutputs::Array'"); + } + + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'BrilligOutputs' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'BrilligOutputs' enum variant: " + tag); } } }; @@ -4151,12 +6288,33 @@ struct MemOp { { std::string name = "MemOp"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "read", read, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "index", index, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "value", value, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "read", read); + break; + case 1: + Helpers::convert_or_throw(val, name, "index", index); + break; + case 2: + Helpers::convert_or_throw(val, name, "value", value); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for MemOp: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "read", read, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "index", index, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "value", value, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "read", read, 0); Helpers::conv_fld_from_array(array, name, "index", index, 1); Helpers::conv_fld_from_array(array, name, "value", value, 2); @@ -4221,11 +6379,29 @@ struct Opcode { { std::string name = "MemoryOp"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "block_id", block_id, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "op", op, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "block_id", block_id); + break; + case 1: + Helpers::convert_or_throw(val, name, "op", op); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for MemoryOp: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "block_id", block_id, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "op", op, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "block_id", block_id, 0); Helpers::conv_fld_from_array(array, name, "op", op, 1); } else { @@ -4253,12 +6429,33 @@ struct Opcode { { std::string name = "MemoryInit"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "block_id", block_id, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "init", init, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "block_type", block_type, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "block_id", block_id); + break; + case 1: + Helpers::convert_or_throw(val, name, "init", init); + break; + case 2: + Helpers::convert_or_throw(val, name, "block_type", block_type); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for MemoryInit: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 3, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "block_id", block_id, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "init", init, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "block_type", block_type, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 3, 0); Helpers::conv_fld_from_array(array, name, "block_id", block_id, 0); Helpers::conv_fld_from_array(array, name, "init", init, 1); Helpers::conv_fld_from_array(array, name, "block_type", block_type, 2); @@ -4289,13 +6486,37 @@ struct Opcode { { std::string name = "BrilligCall"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "id", id, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "id", id); + break; + case 1: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 2: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + case 3: + Helpers::convert_or_throw(val, name, "predicate", predicate); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for BrilligCall: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "id", id, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "id", id, 0); Helpers::conv_fld_from_array(array, name, "inputs", inputs, 1); Helpers::conv_fld_from_array(array, name, "outputs", outputs, 2); @@ -4327,13 +6548,37 @@ struct Opcode { { std::string name = "Call"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "id", id, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "id", id); + break; + case 1: + Helpers::convert_or_throw(val, name, "inputs", inputs); + break; + case 2: + Helpers::convert_or_throw(val, name, "outputs", outputs); + break; + case 3: + Helpers::convert_or_throw(val, name, "predicate", predicate); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Call: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 4, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "id", id, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 4, 0); Helpers::conv_fld_from_array(array, name, "id", id, 0); Helpers::conv_fld_from_array(array, name, "inputs", inputs, 1); Helpers::conv_fld_from_array(array, name, "outputs", outputs, 2); @@ -4404,80 +6649,164 @@ struct Opcode { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'Opcode'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'Opcode'"); - } - if (tag == "AssertZero") { - AssertZero v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'Opcode::AssertZero'"); - } - - value = v; - } else if (tag == "BlackBoxFuncCall") { - BlackBoxFuncCall v; - try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'Opcode::BlackBoxFuncCall'"); - } - - value = v; - } else if (tag == "MemoryOp") { - MemoryOp v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("expected u8 variant tag for enum 'Opcode'"); + } + switch (tag) { + case 0: { + AssertZero v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::AssertZero'"); + } + value = v; + break; + } + case 1: { + BlackBoxFuncCall v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::BlackBoxFuncCall'"); + } + value = v; + break; + } + case 2: { + MemoryOp v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::MemoryOp'"); + } + value = v; + break; + } + case 3: { + MemoryInit v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::MemoryInit'"); + } + value = v; + break; + } + case 4: { + BrilligCall v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::BrilligCall'"); + } + value = v; + break; + } + case 5: { + Call v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::Call'"); + } + value = v; + break; + } + default: std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'Opcode::MemoryOp'"); + throw_or_abort("unknown 'Opcode' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "MemoryInit") { - MemoryInit v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'Opcode::MemoryInit'"); - } - - value = v; - } else if (tag == "BrilligCall") { - BrilligCall v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'Opcode::BrilligCall'"); - } - - value = v; - } else if (tag == "Call") { - Call v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { + throw_or_abort("error converting tag to string for enum 'Opcode'"); + } + if (tag == "AssertZero") { + AssertZero v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::AssertZero'"); + } + + value = v; + } else if (tag == "BlackBoxFuncCall") { + BlackBoxFuncCall v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::BlackBoxFuncCall'"); + } + + value = v; + } else if (tag == "MemoryOp") { + MemoryOp v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::MemoryOp'"); + } + + value = v; + } else if (tag == "MemoryInit") { + MemoryInit v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::MemoryInit'"); + } + + value = v; + } else if (tag == "BrilligCall") { + BrilligCall v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::BrilligCall'"); + } + + value = v; + } else if (tag == "Call") { + Call v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'Opcode::Call'"); + } + + value = v; + } else { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'Opcode::Call'"); + throw_or_abort("unknown 'Opcode' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'Opcode' enum variant: " + tag); } } }; @@ -4564,40 +6893,80 @@ struct ExpressionOrMemory { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'ExpressionOrMemory'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'ExpressionOrMemory'"); - } - if (tag == "Expression") { - Expression v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'ExpressionOrMemory::Expression'"); + throw_or_abort("expected u8 variant tag for enum 'ExpressionOrMemory'"); + } + switch (tag) { + case 0: { + Expression v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ExpressionOrMemory::Expression'"); + } + value = v; + break; + } + case 1: { + Memory v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ExpressionOrMemory::Memory'"); + } + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'ExpressionOrMemory' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "Memory") { - Memory v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'ExpressionOrMemory::Memory'"); + throw_or_abort("error converting tag to string for enum 'ExpressionOrMemory'"); + } + if (tag == "Expression") { + Expression v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ExpressionOrMemory::Expression'"); + } + + value = v; + } else if (tag == "Memory") { + Memory v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ExpressionOrMemory::Memory'"); + } + + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'ExpressionOrMemory' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'ExpressionOrMemory' enum variant: " + tag); } } }; @@ -4619,11 +6988,29 @@ struct AssertionPayload { { std::string name = "AssertionPayload"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "error_selector", error_selector, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "payload", payload, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "error_selector", error_selector); + break; + case 1: + Helpers::convert_or_throw(val, name, "payload", payload); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for AssertionPayload: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "error_selector", error_selector, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "payload", payload, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "error_selector", error_selector, 0); Helpers::conv_fld_from_array(array, name, "payload", payload, 1); } else { @@ -4669,11 +7056,29 @@ struct OpcodeLocation { { std::string name = "Brillig"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "acir_index", acir_index, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "brillig_index", brillig_index, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "acir_index", acir_index); + break; + case 1: + Helpers::convert_or_throw(val, name, "brillig_index", brillig_index); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for Brillig: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "acir_index", acir_index, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "brillig_index", brillig_index, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "acir_index", acir_index, 0); Helpers::conv_fld_from_array(array, name, "brillig_index", brillig_index, 1); } else { @@ -4726,40 +7131,80 @@ struct OpcodeLocation { if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { throw_or_abort("expected 1 entry for enum 'OpcodeLocation'; got " + std::to_string(o.via.map.size)); } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'OpcodeLocation'"); - } - if (tag == "Acir") { - Acir v; + if (Helpers::is_int_keyed_map(o)) { + // `Format::MsgpackTagged` — int-keyed variant. + uint8_t tag; try { - o.via.map.ptr[0].val.convert(v); + o.via.map.ptr[0].key.convert(tag); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'OpcodeLocation::Acir'"); + throw_or_abort("expected u8 variant tag for enum 'OpcodeLocation'"); + } + switch (tag) { + case 0: { + Acir v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'OpcodeLocation::Acir'"); + } + value = v; + break; + } + case 1: { + Brillig v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'OpcodeLocation::Brillig'"); + } + value = v; + break; + } + default: + std::cerr << o << std::endl; + throw_or_abort("unknown 'OpcodeLocation' enum variant tag: " + std::to_string(tag)); } - - value = v; - } else if (tag == "Brillig") { - Brillig v; + } else { + // `Format::Msgpack` (MAP, string-keyed) or `Format::MsgpackCompact` + // unit variant (bare STR) — both dispatch on the variant name. + std::string tag; try { - o.via.map.ptr[0].val.convert(v); + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'OpcodeLocation::Brillig'"); + throw_or_abort("error converting tag to string for enum 'OpcodeLocation'"); + } + if (tag == "Acir") { + Acir v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'OpcodeLocation::Acir'"); + } + + value = v; + } else if (tag == "Brillig") { + Brillig v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'OpcodeLocation::Brillig'"); + } + + value = v; + } else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'OpcodeLocation' enum variant: " + tag); } - - value = v; - } else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'OpcodeLocation' enum variant: " + tag); } } }; @@ -4807,13 +7252,42 @@ struct Circuit { { std::string name = "Circuit"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "function_name", function_name, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "opcodes", opcodes, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "private_parameters", private_parameters, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "public_parameters", public_parameters, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "return_values", return_values, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "assert_messages", assert_messages, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "function_name", function_name); + break; + case 1: + Helpers::convert_or_throw(val, name, "opcodes", opcodes); + break; + case 2: + Helpers::convert_or_throw(val, name, "private_parameters", private_parameters); + break; + case 3: + Helpers::convert_or_throw(val, name, "public_parameters", public_parameters); + break; + case 4: + Helpers::convert_or_throw(val, name, "return_values", return_values); + break; + case 5: + Helpers::convert_or_throw(val, name, "assert_messages", assert_messages); + break; + default: + // `#[tagged(allow_unknown_tags)]` on the Rust side: + // silently skip any tag we don't recognize. + break; + } + }); + } else { + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "function_name", function_name, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "opcodes", opcodes, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "private_parameters", private_parameters, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "public_parameters", public_parameters, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "return_values", return_values, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "assert_messages", assert_messages, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; Helpers::conv_fld_from_array(array, name, "function_name", function_name, 0); @@ -4845,9 +7319,26 @@ struct BrilligBytecode { { std::string name = "BrilligBytecode"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "function_name", function_name, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "bytecode", bytecode, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "function_name", function_name); + break; + case 1: + Helpers::convert_or_throw(val, name, "bytecode", bytecode); + break; + default: + // `#[tagged(allow_unknown_tags)]` on the Rust side: + // silently skip any tag we don't recognize. + break; + } + }); + } else { + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "function_name", function_name, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "bytecode", bytecode, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; Helpers::conv_fld_from_array(array, name, "function_name", function_name, 0); @@ -4875,9 +7366,26 @@ struct Program { { std::string name = "Program"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "functions", functions, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "unconstrained_functions", unconstrained_functions, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "functions", functions); + break; + case 1: + Helpers::convert_or_throw(val, name, "unconstrained_functions", unconstrained_functions); + break; + default: + // `#[tagged(allow_unknown_tags)]` on the Rust side: + // silently skip any tag we don't recognize. + break; + } + }); + } else { + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "functions", functions, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "unconstrained_functions", unconstrained_functions, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; Helpers::conv_fld_from_array(array, name, "functions", functions, 0); @@ -4905,10 +7413,28 @@ struct ProgramWithoutBrillig { { std::string name = "ProgramWithoutBrillig"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "functions", functions, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "functions", functions); + break; + case 1: + // Field is `std::monostate` — wire entry intentionally discarded. + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for ProgramWithoutBrillig: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "functions", functions, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "functions", functions, 0); } else { throw_or_abort("expected MAP or ARRAY for " + name); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp index cf99681e446..67b45cdb561 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp @@ -1,3 +1,10 @@ +// AUTO-GENERATED — DO NOT EDIT. +// +// Generated by the `cpp_codegen` tests in `acvm-repo/acir/src/lib.rs`. +// To regenerate, run: +// +// NOIR_CODEGEN_OVERWRITE=1 cargo test -p acir cpp_codegen +// #pragma once #include "barretenberg/serialize/msgpack_impl.hpp" @@ -32,6 +39,9 @@ struct Helpers { { auto it = kvmap.find(field_name); if (it != kvmap.end()) { + if (!is_optional && it->second->type == msgpack::type::NIL) { + throw_or_abort("nil value for required field: " + struct_name + "::" + field_name); + } try { it->second->convert(field); } catch (const msgpack::type_error&) { @@ -54,6 +64,9 @@ struct Helpers { throw_or_abort("index out of bounds: " + struct_name + "::" + field_name + " at " + std::to_string(index)); } auto element = array.ptr[index]; + if (element.type == msgpack::type::NIL) { + throw_or_abort("nil value for required field: " + struct_name + "::" + field_name); + } try { element.convert(field); } catch (const msgpack::type_error&) { @@ -61,6 +74,77 @@ struct Helpers { throw_or_abort("error converting into field " + struct_name + "::" + field_name); } } + + /// Convert `val` into `field`, or throw a focused error mentioning + /// the struct + field name. Used by the int-keyed dispatch path + /// where each `switch` case populates one field directly. + template + static void convert_or_throw(msgpack::object const& val, + std::string const& struct_name, + std::string const& field_name, + T& field) + { + try { + val.convert(field); + } catch (const msgpack::type_error&) { + std::cerr << val << std::endl; + throw_or_abort("error converting into field " + struct_name + "::" + field_name); + } + } + + /// Whether `o` is a non-empty MAP whose first key is an integer. + /// This is the signature of `Format::MsgpackTagged`: int keys for + /// struct field tags and enum variant tags. Legacy `Format::Msgpack` + /// keys are always strings, so a positive-integer first key is a + /// reliable shape discriminator between the two. + static bool is_int_keyed_map(msgpack::object const& o) + { + return o.type == msgpack::type::MAP && o.via.map.size > 0 && + o.via.map.ptr[0].key.type == msgpack::type::POSITIVE_INTEGER; + } + + /// Iterate an int-keyed MAP and invoke `dispatch(tag, val)` for each + /// `(u8, msgpack::object)` entry. The per-tag `switch` inside the + /// caller's lambda decides which field (or variant) to populate; + /// unknown tags fall through to `default` and are silently skipped, + /// matching the `MsgpackTagged` decoder's forward-compat policy + /// (`allow_unknown_tags` / retired tags drained). + template + static void int_map_dispatch(msgpack::object const& o, std::string const& name, Dispatch&& dispatch) + { + for (uint32_t i = 0; i < o.via.map.size; ++i) { + uint8_t tag; + try { + o.via.map.ptr[i].key.convert(tag); + } catch (const msgpack::type_error&) { + std::cerr << o.via.map.ptr[i].key << std::endl; + throw_or_abort("expected u8 tag in int-keyed map for " + name); + } + dispatch(tag, o.via.map.ptr[i].val); + } + } + + /// Cap a `MAP` or `ARRAY` entry count against `active + reserved`. + /// Under-length wires are caught downstream (`conv_fld_from_array` + /// errors out of bounds; `conv_fld_from_kvmap` errors on missing + /// required keys), so we only need the upper bound here. + /// + /// * Up to `reserved` extra trailing entries are tolerated as + /// retired fields (`#[tagged(reserved(...))]` on the Rust side). + /// * Anything beyond that is forward-compat drift that the + /// producer only emits when newer fields were added. The + /// Rust-side cue is `#[tagged(allow_unknown_tags)]`; the + /// message points at it so a reviewer can see the opt-in. + static void check_size(uint32_t actual, std::string const& name, uint32_t active, uint32_t reserved) + { + uint32_t max_size = active + reserved; + if (actual > max_size) { + throw_or_abort(name + " has " + std::to_string(actual) + " entries but at most " + + std::to_string(max_size) + " are expected (" + std::to_string(active) + " active + " + + std::to_string(reserved) + + " reserved); opt into `#[tagged(allow_unknown_tags)]` on the Rust type to accept extras"); + } + } }; } // namespace Witnesses @@ -120,11 +204,29 @@ struct StackItem { { std::string name = "StackItem"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "index", index, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "witness", witness, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "index", index); + break; + case 1: + Helpers::convert_or_throw(val, name, "witness", witness); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for StackItem: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 2, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "index", index, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "witness", witness, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 2, 0); Helpers::conv_fld_from_array(array, name, "index", index, 0); Helpers::conv_fld_from_array(array, name, "witness", witness, 1); } else { @@ -148,10 +250,25 @@ struct WitnessStack { { std::string name = "WitnessStack"; if (o.type == msgpack::type::MAP) { - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "stack", stack, false); + if (Helpers::is_int_keyed_map(o)) { + Helpers::int_map_dispatch(o, name, [&](uint8_t tag, msgpack::object const& val) { + switch (tag) { + case 0: + Helpers::convert_or_throw(val, name, "stack", stack); + break; + default: + std::cerr << val << std::endl; + throw_or_abort("unknown tag for WitnessStack: " + std::to_string(tag)); + } + }); + } else { + Helpers::check_size(o.via.map.size, name, 1, 0); + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "stack", stack, false); + } } else if (o.type == msgpack::type::ARRAY) { auto array = o.via.array; + Helpers::check_size(array.size, name, 1, 0); Helpers::conv_fld_from_array(array, name, "stack", stack, 0); } else { throw_or_abort("expected MAP or ARRAY for " + name);