Skip to content

feat: Variadic concat#7231

Open
jbencin-stacks wants to merge 9 commits into
stacks-network:pox-wf-integrationfrom
jbencin-stacks:feat/variadic-concat
Open

feat: Variadic concat#7231
jbencin-stacks wants to merge 9 commits into
stacks-network:pox-wf-integrationfrom
jbencin-stacks:feat/variadic-concat

Conversation

@jbencin-stacks
Copy link
Copy Markdown
Contributor

@jbencin-stacks jbencin-stacks commented May 22, 2026

Description

Allow concat to take variable arguments. This allows much cleaner and more efficient buffer building than in Clarity 5:

;; Clarity 5 and below: nested calls required
(concat (concat (concat 0x11 amount-bytes) fee-bytes) chain-id)

;; Clarity 6: flat, variadic call
(concat 0x11 amount-bytes fee-bytes chain-id)

Applicable issues

Additional info (benefits, drawbacks, caveats)

This change means that buffer building costs now scale linearly with the number of arguments, rather than quadratically, since we can eliminate doing a buffer allocation for each argument. We may wish to update the costs contract to reflect the changes

Checklist

  • Test coverage for new or modified code paths
  • For new Clarity features or consensus changes, add property tests (see docs/property-testing.md)
  • Changelog fragment(s) or "no changelog" label added (see changelog.d/README.md)
  • Required documentation changes (e.g., rpc/openapi.yaml for RPC endpoints, event-dispatcher.md for new events)
  • New clarity functions have corresponding PR in clarity-benchmarking repo

jbencin-stacks and others added 9 commits May 22, 2026 16:38
`concat` now accepts 2 or more sequence arguments when running under
`ClarityVersion::Clarity6`. The 2-argument case is byte-for-byte
equivalent to the previous v205 implementation, so older-version
contracts running at Epoch 4.0 see no behavior change.

The variadic form is folded left-to-right, charging the v205 cost
formula on every fold step. This means `(concat a b c)` costs the same
as the equivalent `(concat (concat a b) c)` — no arbitrage between the
two syntactic forms — while still benefiting from a single allocation
path at runtime.

Implementation:
- Runtime: new `special_concat_v600` in `functions/sequences.rs`;
  `special_concat` now dispatches by epoch (v200 for 2.0, v205 for
  2.05–3.4, v600 for 4.0+).
- Type checker: `check_special_concat` switches to
  `check_arguments_at_least(2)` for Clarity 6+ and folds
  `least_supertype` / `max_len` across all args. The 2-arg path is
  preserved exactly for older versions.

Tests cover variadic over buff, string-ascii, and list; arity errors
(0 and 1 arg); mixed-type rejection at both runtime and analysis time;
and a regression check that pre-Clarity-6 contracts still reject
3-arg `concat`.

Closes stacks-network#7112

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jbencin-stacks jbencin-stacks marked this pull request as ready for review May 26, 2026 16:07
@coveralls
Copy link
Copy Markdown

Coverage Report for CI Build 26460113011

Coverage decreased (-38.4%) to 47.53%

Details

  • Coverage decreased (-38.4%) from the base build.
  • Patch coverage: 36 uncovered changes across 4 files (84 of 120 lines covered, 70.0%).
  • 88736 coverage regressions across 345 files.

Uncovered Changes

File Changed Covered %
clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs 52 38 73.08%
clarity/src/vm/functions/sequences.rs 55 43 78.18%
clarity/src/vm/mod.rs 6 0 0.0%
clarity-types/src/types/mod.rs 7 3 42.86%

Coverage Regressions

88736 previously-covered lines in 345 files lost coverage.

Top 10 Files by Coverage Loss Lines Losing Coverage Coverage
stackslib/src/chainstate/stacks/db/transactions.rs 8105 7.51%
stackslib/src/chainstate/stacks/db/blocks.rs 4478 35.57%
stackslib/src/chainstate/stacks/transaction.rs 4313 9.87%
stackslib/src/chainstate/burn/db/sortdb.rs 4193 42.89%
stackslib/src/chainstate/stacks/boot/mod.rs 3564 13.75%
stackslib/src/net/chat.rs 3165 27.23%
stackslib/src/chainstate/burn/operations/leader_block_commit.rs 2579 18.81%
stackslib/src/net/db.rs 1962 28.92%
stacks-signer/src/signerdb.rs 1578 35.21%
stackslib/src/chainstate/stacks/index/test/node.rs 1317 0.0%

Coverage Stats

Coverage Status
Relevant Lines: 220626
Covered Lines: 104864
Line Coverage: 47.53%
Coverage Strength: 12799704.82 hits per line

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants