ProvableHQ / ProvableHQ/python-sdk
codegen: support array types everywhere (struct/record fields, mapping values, function I/O), recursively
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 45
- Forks
- 51
- Ø Merge
- 3 T. 18 Std.
- Gemergte PRs (30 T.)
- 2
Beschreibung
Summary
aleo.codegen does not support array types. codegen/_emit.py::resolve_ty maps only {"Primitive": …} and {"Struct": …}; every other shape falls through to raise ValueError("Unsupported ABI type: …"). Arrays are represented in the ABI as {"Array": {"element": <ty>, "length": N}}, which has no branch — so any struct/record field (or mapping value) that is an array breaks emit_module.
Structs (nested structs, cross-program ref checks) work; this is specific to arrays.
What "support arrays" means here
An Aleo array is just a fixed-length collection of a single element type, and that element can itself be any type:
- a primitive —
[u8; 32],[field; 4],[bool; 8],[address; 3] - a struct —
[Foo; 2] - another array (arbitrary nesting) —
[[u8; 4]; 3],[[Foo; 2]; 5]
So the fix must be recursive: resolve_ty should resolve the element type (which may recurse into a primitive, a struct, or a nested array) and build the Python representation from it. There is no fixed depth.
Scope — arrays must work in EVERY type position
Array support should be complete wherever the codegen resolves a type:
- Struct fields —
struct Foo: xs as [u8; 4u32]; - Record fields —
record R: data as [field; 8u32].private; - Mapping values —
mapping m: key as ...; value as [u8; 32u32]; - Function input / output positions —
input r0 as [u8; 4u32].private;/output r0 as [Foo; 2u32].private;
Note on (4): emit_module currently emits struct/record dataclasses, mapping-value decoders, and the raw ABI dict, but does not emit typed function signatures at all — so today array function I/O neither works nor errors, it's simply unbound. Completing this item therefore also means the codegen must resolve function input/output types (arrays included), not just struct/record/mapping types.
Reproduction
from aleo.abi import generate_abi
from aleo.mainnet import Program
from aleo.codegen._emit import emit_module
src = """program arr3.aleo;
struct Foo:
xs as [u8; 4u32];
function usefoo:
input r0 as Foo.private;
output r0 as Foo.private;
"""
abi = generate_abi(Program.from_source(src), "mainnet")
emit_module(abi)
# ValueError: Unsupported ABI type:
# {'Array': {'element': {'Primitive': {'UInt': 'U8'}}, 'length': 4}}
Runtime decoding is unaffected — codegen/runtime.py::_parse_array already turns array plaintext into Python lists (see the passing test_parse_nested_struct_and_array). The gap is purely on the emission/type-mapping side.
Suggested fix
resolve_ty— add a recursive"Array"case. Resolve the element typeet = resolve_ty(ty["Array"]["element"]), then:- annotation:
list[<et.annotation>] - encode:
"[ " + ", ".join(<et.encode(x)> for x in e) + " ]"(Aleo array literal). The element encoder is applied per element, so[Foo; 2]callsFoo.to_plaintext()per element and[[u8;4];3]recurses. - decode: map the element decoder over the list — pass-through for primitive elements,
Elem.from_decodedfor struct elements, and recurse for nested arrays. (runtime.parse_plaintextalready yields nested lists, so decode just re-wraps struct elements.)
- annotation:
_check_struct_refs— descend into array elements so a[SomeStruct; N]field/value still resolves its struct reference (currently only top-level{"Struct"}is checked; a struct nested in an array is skipped).- Function I/O typing — if/when function signatures are emitted, route their input/output types through the same
resolve_tyso arrays are covered there too.
Robust array test fixture (required)
Add a dedicated ABI fixture (sibling to tests/fixtures/shield_swap_v3.abi.json) that exercises arrays in every position and nesting, and drive emit + round-trip (to_plaintext → from_plaintext) tests off it:
- array of each primitive family:
[u8; N]/int,[bool; N],[address; N],[field; N](field/group/scalar) - array of struct:
[Foo; N] - nested array:
[[u8; 4]; 3], and array-of-array-of-struct[[Foo; 2]; 3] - an array field inside a struct, inside a record, as a mapping value, and in a function input and output
- struct containing an array containing a struct (mixed recursion)
Round-trip assertions should confirm: emitted annotations (list[...], nested), to_plaintext produces valid Aleo array literals for each case, and from_plaintext/from_decoded reconstructs the exact Python value (including struct elements and nesting). Also keep a negative test asserting a clear error for genuinely unsupported shapes.
Why it wasn't caught
The only real ABI fixture (tests/fixtures/shield_swap_v3.abi.json) is 258 Primitive + 16 Struct with zero arrays, and test_codegen_emit.py only exercises resolve_ty on primitives + structs.
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Start in codegen/_emit.py at resolve_ty and _check_struct_refs, then inspect tests/test_codegen_emit.py and the existing tests/fixtures/shield_swap_v3.abi.json fixture. Add coverage for recursive arrays in struct, record, mapping, and function I/O positions, including nested structs and arrays; done means emission and plaintext round-trips pass while unsupported ABI shapes still raise clearly.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- testing, tooling
- Issue-Typ
- Feature
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Ruhig
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 65/100