Skip to content

feat: add 256-bit A/B arithmetic, hashing-fee hook, passthrough cleanup#11

Merged
QuickMythril merged 1 commit into
mainfrom
feat/at-vm-batch
Jul 22, 2026
Merged

feat: add 256-bit A/B arithmetic, hashing-fee hook, passthrough cleanup#11
QuickMythril merged 1 commit into
mainfrom
feat/at-vm-batch

Conversation

@QuickMythril

Copy link
Copy Markdown
Member

Summary

The planned "jar-fork batch" — the three AT-VM features that require changes inside the jar (unlike the map functions, which ride the platform passthrough range). One commit, 4f70a18.

1. A/B 256-bit arithmetic (0x01400x0147)

The eight spec-reserved ops (Add_A_To_BDiv_B_By_A) that CIYAM's at_api.html documents and Signum implemented (cases 320–327 in AtApiController.java); Qortal never did. A1..A4/B1..B4 are treated as one 256-bit little-endian value, matching Signum's limb order. Add/sub/mul wrap modulo 2^256 and are bit-identical to Signum's results.

Two deliberate divergences from Signum, both documented in javadoc:

  • Division is unsigned (Signum's is signed — differs only when a top bit is set; a test pins our behavior).
  • Divide-by-zero throws IllegalOperationException → machine error / onErrorAddress, matching this library's existing DIV_DAT/DIV_VAL/MOD_DAT convention (Signum silently no-ops).

2. Hashing-fee discrimination

New API.getHashingFunctionSteps(OpCode, FunctionCode, MachineState) hook + FunctionCode.isHashingFunction() (codes 0x02000x0207), consulted by MachineState.execute() for the hash built-ins. The CIYAM spec explicitly recommends charging more for hash functions; no chain could because the pricing path never saw the FunctionCode. Default delegates down the existing chain, so with no platform override, charged steps are byte-for-byte identical — including for consumers that override only the general 3-arg getOpCodeSteps (pinned by test).

3. Platform passthrough cleanup

The ad-hoc 0x0500–0x06ff literals in FunctionCode.valueOf become documented PLATFORM_CODE_START/PLATFORM_CODE_END constants + isPlatformFunctionCode(int), with the dispatch contract (precheck + execute) spelled out in API_PASSTHROUGH javadoc. valueOf behavior is unchanged for every input (boundary-tested).

Backward compatibility (consensus-critical)

  • 0x01400x0147 were previously unmapped → fatal IllegalFunctionCodeException, so no deployed bytecode can contain them on a live execution path; existing codes untouched.
  • Hashing pricing defaults are byte-identical without an explicit platform override.
  • Passthrough change is refactor + docs only.
  • Nothing reaches qortium-core until it deliberately bumps its pinned ciyam-at.version (currently 33df17d). The Core consumer (ChainFunctionCode/ChainATAPI) was checked and needs no changes.

Verification

  • mvn -B clean verify: 207 tests, 0 failures, 0 errors (baseline on main: 179) — verified independently in a clean run, not just the implementation pass.
  • 28 new tests: 18 arithmetic (per-op direction/result register, carry/borrow across all four limbs, wrap, cross-limb mul/div, truncating + unsigned-vs-signed division discriminator, div-by-zero both directions), 6 hashing-hook (default unchanged, override scope, delegation-chain compatibility), 4 passthrough (range predicates, valueOf boundaries, dispatch of an unenumerated code, wrong-signature precheck rejection).
  • 3 mutation checks (ADD→SUB, hook bypass, silent div-by-zero) each made the new tests fail before restoration.

Merge note

Squash is fine here (nothing pins this commit). Core repin is intentionally deferred — this batch should not ride the pre-70,000 release; repin when a feature actually consumes it.

🤖 Generated with Claude Code

Batch of three AT-library features for the next pinned release:

* A/B 256-bit arithmetic (function codes 0x0140-0x0147): ADD_A_TO_B,
  ADD_B_TO_A, SUB_A_FROM_B, SUB_B_FROM_A, MUL_A_BY_B, MUL_B_BY_A,
  DIV_A_BY_B, DIV_B_BY_A. A1..A4 / B1..B4 are treated as one 256-bit
  little-endian unsigned integer (least significant register first),
  matching Signum's extended API codes and argument direction. Add,
  subtract and multiply wrap modulo 2^256 (bit-identical to Signum's
  signed two's-complement results). Division is unsigned and truncating,
  and divide-by-zero throws IllegalOperationException to match this
  library's existing DIV_DAT/DIV_VAL error convention (Signum instead
  silently no-ops; a fatal error is safer for consensus code).

* Hashing-fee discrimination: new API.getHashingFunctionSteps() hook is
  consulted for the built-in hashing functions (MD5/RMD160/SHA256/
  HASH160 variants, see FunctionCode.isHashingFunction()) so platforms
  can price hashing differently from the flat per-function-call cost
  without matching raw function code values. Default delegates to the
  existing getOpCodeSteps() overloads, so with no override execution
  costs are unchanged, including for platforms that only override the
  general external-function overload.

* Platform passthrough cleanup: the 0x0500-0x06ff platform-specific
  range is now expressed via documented PLATFORM_CODE_START/END
  constants and FunctionCode.isPlatformFunctionCode(), with expanded
  API_PASSTHROUGH javadoc describing the dispatch contract. Behavior
  of valueOf() is unchanged.

All existing bytecode executes with identical behavior and cost; new
function codes were previously fatal "unknown function code" errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@QuickMythril
QuickMythril merged commit 76db49f into main Jul 22, 2026
4 checks passed
@QuickMythril
QuickMythril deleted the feat/at-vm-batch branch July 22, 2026 03:14
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.

1 participant