codegen: support array types everywhere (struct/record fields, mapping values, function I/O), recursively

未关闭
#48 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
65/100
Issue 类型
功能
描述清晰度
描述清楚
活跃度
冷清
技术栈
python
领域
testing, tooling

调研方向

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.

由索引模型根据 Issue 内容生成。

描述

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:

  1. Struct fieldsstruct Foo: xs as [u8; 4u32];
  2. Record fieldsrecord R: data as [field; 8u32].private;
  3. Mapping valuesmapping m: key as ...; value as [u8; 32u32];
  4. Function input / output positionsinput 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

  1. resolve_ty — add a recursive "Array" case. Resolve the element type et = 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] calls Foo.to_plaintext() per element and [[u8;4];3] recurses.
    • decode: map the element decoder over the list — pass-through for primitive elements, Elem.from_decoded for struct elements, and recurse for nested arrays. (runtime.parse_plaintext already yields nested lists, so decode just re-wraps struct elements.)
  2. _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).
  3. Function I/O typing — if/when function signatures are emitted, route their input/output types through the same resolve_ty so 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_plaintextfrom_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.

主要语言
Python
星标
45
派生
51
平均合并
3 天 18 小时
30 天内合并 PR
2

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

ProvableHQ/python-sdk 的其他 Issue

查看 ProvableHQ/python-sdk 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。