Skip to content

fix(template): accept array covenant inputs in artifacts - #4

Merged
louisinger merged 2 commits into
masterfrom
fix/artifact-array-inputs
Oct 22, 2026
Merged

louisinger merged 2 commits into
masterfrom
fix/artifact-array-inputs

Conversation

@Kukks

@Kukks Kukks commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Artifacts whose functions take an array covenant input are refused at registration with unsupported arkade input type "bytes[3]". arkadec emits that type for a bytes[N] function parameter, for example three signatures for an N-of-N release. So a contract that uses one cannot be watched at all, even when the watch only spends a function that takes no inputs, like renew or complete.

This parses covenant input types the same way constructor inputs are already parsed: through validType, a scalar element with a size up to maxArray. A template that would spend a function taking an array input is now refused with ErrUnsupported, because the instance builder fills one stack item per input and does not flatten arrays. Nothing changes for templates that work today. If you'd rather support filling arrays instead of refusing, I'm happy to take it that way.

I hit this watching Portcullis vaults: their release and unvault functions take bytes[3] signature arrays, while renew and complete take none.

TestParseArtifactArrayInput covers the accepted and refused types. TestArrayInputs covers a template next to a function with an array input (it parses) and a template spending that function (ErrUnsupported). go test passes in pkg/template and in the root module's packages that don't need Postgres; I had no database locally for the Postgres-backed suites.

Summary by CodeRabbit

  • New Features
    • Arkade inputs can now use supported scalar arrays, such as fixed-size byte arrays, within the existing array-size limit.
  • Limitations
    • Array inputs are not supported for functions used by a template. Struct inputs remain unsupported, and invalid array types—including empty, nested, or unsupported scalar arrays—are rejected.

arkadec emits bytes[3] for a bytes[N] function parameter. Parse it like a constructor array; refuse a template that would spend such a function, since the instance fills one stack item per input.
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4892565d-9a74-4c4e-bbc2-d463f2232af8
📥 Commits

Reviewing files that changed from the base of the PR and between a1766ec and cc0b7c1.

📒 Files selected for processing: 1
  • pkg/template/template_test.go

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

Arkade artifact parsing now accepts supported scalar array inputs. Template parsing returns ErrUnsupported when a template spends a function with an array input.

Changes

Arkade Array Inputs

Layer / File(s) Summary
Accept and validate scalar array inputs
pkg/template/artifact.go, pkg/template/artifact_test.go
Artifact parsing accepts supported scalar arrays, subject to the existing size limit. Tests cover bytes[3] and invalid array types.
Reject spending functions with array inputs
pkg/template/template.go, pkg/template/template_test.go
parser.spend returns ErrUnsupported for an array-typed function input. Tests check that parsing succeeds when the template does not spend the function and fails when it does.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: louisinger

Merge Risk: ⚪ Minimal · up to cc0b7

The added test covers accepting an array input when its function is not spent and rejecting a template that spends it. No actionable merge risk is established in the reviewed scope.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly identifies the main change: template artifacts now accept array covenant inputs.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 2
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@arkana-ai-bot arkana-ai-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review of fix(template): accept array covenant inputs in artifacts

Scope: pkg/template/artifact.go and pkg/template/template.go. No VTXO/signing/forfeit/round/exit paths are touched — this is template validation only.


Correctness

artifact.go:224 — validType(in.Type, nil) substitution

The replacement is sound. validType with structs=nil accepts exactly scalars and elementType[N] where elementType ∈ scalarTypes and 1 ≤ N ≤ maxArray(1024). The nil map lookup (structs[t]) returns false without panic in Go, so struct types are still rejected. Nested arrays (bytes[3][2]) are rejected because the first group of arrayType ([a-z0-9]+) cannot itself be an array expression — the regex enforces a single bracket pair.

template.go:539–542 — spend guard

Placement is correct: the check fires before the arity check, so a template referencing a function with any array covenant input gets ErrUnsupported regardless of how many arguments the template provides. The guard only runs when f.Arkade != nil (the want slice is only populated from f.Arkade.Inputs), so plain tapscript functions without covenants are unaffected.

Artifact ID stability

Artifacts already stored in the database had scalar-only covenant inputs (array types were unconditionally rejected before). This change does not alter IDs for any previously valid artifact. New artifacts containing bytes[N] covenant inputs hash correctly through d.json(), which round-trips the Type string verbatim.


Test coverage

TestParseArtifactArrayInput covers:

  • Acceptance: bytes[3] parses and the type is preserved in Definition.
  • Rejection: float[3] (non-scalar element), bytes[0] (zero index, rejected by regex), bytes[] (empty index), bytes[3][2] (nested), signature[3] (signature not in scalarTypes).

TestArrayInputs covers:

  • Template with array input on a non-spent function → parses OK.
  • Template spending a function with an array input → ErrUnsupported with the input name in the message.

Both success and failure paths are exercised. The error sentinel (ErrUnsupported) and message content are asserted.


Minor observations (non-blocking)

  1. TestArrayInputs is index-dependent (fn=0, fn=1 into releaseDoc's functions array). If releaseDoc's function order ever changes, the test's intent silently inverts. A comment naming the function at each index would make this more robust, e.g.:

    // fn=0: timelockClaim (not spent by the template)
    // fn=1: nonInteractiveClaim (the function the template spends)

    No correctness issue today.

  2. "signature[3]" rejection is tested and correct (signature is not in scalarTypes), but it is not possible to construct a bytes[N] of signatures through the compiler anyway. The test is still valuable as a negative case.

  3. The PR description is accurate that filling arrays in the instance builder is out of scope here. If array filling is added later, the guard at template.go:539–542 is the right place to remove the restriction, and the comment in the error message already signals why it is there.


No protocol issues, no security issues, no cross-repo surface changes. The fix is minimal and correct.

The spent and unspent functions were addressed by index into releaseDoc, so reordering its functions would silently swap what each half of the test checks.
@Kukks

Kukks commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @arkana-ai-bot. cc0b7c1 picks the two functions by name (exit, which the template leaves alone, and release, which it spends) instead of by index, and the test fails outright if releaseDoc loses either one.

@arkana-ai-bot

arkana-ai-bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Confirmed — cc0b7c1 resolves observation #1 cleanly. The helper now iterates by name and calls t.Fatalf("releaseDoc has no function %q", name) if neither "exit" nor "release" is found, so any reordering or renaming of releaseDoc's functions causes an explicit, descriptive test failure rather than a silent index swap. Nothing left to flag there.

@arkana-ai-bot arkana-ai-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Follow-up pass — 1 commit since a1766ec (cc0b7c1, test-only). 1/1 prior observations fixed; 0 remain.


Prior-issue closure

Observation #1 — index-dependent function selection in TestArrayInputs → Fixed in cc0b7c1.

The withInput helper was changed from fn int (a positional index into releaseDoc.functions) to name string. It now iterates def["functions"] by the "name" key, injects the bytes[3] input onto the matching entry, and calls t.Fatalf("releaseDoc has no function %q", name) if neither "exit" nor "release" is found. Any future reordering or renaming of releaseDoc's functions now produces an explicit, descriptive test failure rather than a silent test-intent swap. The t.Fatalf inside the edited closure terminates the test goroutine correctly.

Observation #2 — "signature[3]" negative case → No longer applicable (informational note; no code change warranted).

Observation #3 — future array-fill removal point → No longer applicable (architectural note; no change warranted).


Incremental diff assessment

Only pkg/template/template_test.go changed. No production code, no protocol paths, no public API surface. The fix is correct and minimal.

No new findings.

@louisinger
louisinger merged commit 667823c into master Oct 22, 2026
10 of 11 checks passed
@louisinger
louisinger deleted the fix/artifact-array-inputs branch October 22, 2026 13:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants