Skip to content

feat: add BigDecimal type to CVM (bounty #5)#578

Open
aglichandrap wants to merge 1 commit into
Convex-Dev:developfrom
aglichandrap:feature/bigdecimal
Open

feat: add BigDecimal type to CVM (bounty #5)#578
aglichandrap wants to merge 1 commit into
Convex-Dev:developfrom
aglichandrap:feature/bigdecimal

Conversation

@aglichandrap

Copy link
Copy Markdown

Summary

Implements arbitrary-precision decimal arithmetic for the CVM numeric tower, fulfilling bounty #5.

Changes

  • CVMBigDecimal.java: Wraps java.math.BigDecimal, extends ANumeric

    • Exact decimal arithmetic (add, sub, multiply, divide)
    • Type promotion: Decimal op Integer → Decimal, Decimal op Double → Double
    • CAD3 encoding: tag 0x1a + VLQ signed scale + VLQ byte count + unscaled bytes
    • Canonical if and only if value has meaningful fractional digits (integers stay as Long/BigInteger)
  • Decimal.java: Type class for CVMBigDecimal registered as Types.DECIMAL

  • Core.java: Registers bigdecimal (code 260) constructor and bigdecimal? (code 261) predicate

  • CAD3Encoder.java: Decodes tag 0x1a → reads VLQ scale, VLQ byte count, unscaled bytes → constructs CVMBigDecimal

  • Juice.java: costNumeric() charges proportional to unscaled byte length (same as BigInteger)

  • RT.java: ensureBigDecimal() conversion from any numeric type

  • Tag.java: BIG_DECIMAL = 0x1a

  • Symbols.java: BIGDECIMAL, BIGDECIMAL_Q

Design Decisions

  • Code 260 for bigdecimal constructor, 261 for bigdecimal? predicate
  • Tag 0x1a for wire format (between BIG_INTEGER=0x19 and DOUBLE=0x1D)
  • Canonicality: Only decimals with fractional digits are canonical; integers always reduce to CVMLong/CVMBigInteger
  • Division: Non-terminating decimal division throws ArithmeticException (preserves exactness)
  • Numeric dispatch: CVMBigDecimal handles Integer operands directly; falls back to Double for CVMDouble operands

Fixes #5

Implements arbitrary-precision decimal arithmetic for the CVM numeric tower.

- CVMBigDecimal.java: wraps java.math.BigDecimal, extends ANumeric
  - Exact decimal arithmetic (add, sub, multiply, divide)
  - Type promotion: Decimal op Integer -> Decimal, Decimal op Double -> Double
  - CAD3 encoding: tag 0x1a + VLQ scale + VLQ byte count + unscaled bytes
  - Canonical if and only if value has meaningful fractional digits

- Decimal.java: type class for CVMBigDecimal (Types.DECIMAL)
- Core.java: register 'bigdecimal' (code 260) constructor and 'bigdecimal?' (code 261) predicate
- CAD3Encoder.java: decode tag 0x1a for BigDecimal wire format
- Juice.java: costNumeric() handles CVMBigDecimal (proportional to unscaled byte length)
- RT.java: ensureBigDecimal() conversion utility
- Tag.java: BIG_DECIMAL = 0x1a
- Symbols.java: BIGDECIMAL, BIGDECIMAL_Q

Fixes Convex-Dev#5
@mikera

mikera commented Jul 6, 2026

Copy link
Copy Markdown
Member

(Claude Comment) Thanks @aglichandrap — putting this one formally on hold rather than into code review.

The reason is upstream of the implementation: we first need to determine whether a decimal type belongs in the CVM numeric tower at all. A new type is a permanent consensus commitment — the CAD3 tag allocation (0x1a is currently unallocated, but allocating it is forever), plus equality/hashing/promotion semantics across the tower, plus juice pricing. Those are specification decisions that belong in a CAD design discussion in the design repo, not a code PR — and the outcome may legitimately be "no" (many platforms deliberately stay with integer + IEEE double, pushing fixed-point decimal semantics to actor-level libraries).

If the design discussion concludes it makes sense, it would land via the versioned migration mechanism (v2 at the earliest, using the regNonGenesis pattern) and this PR would be a strong starting point for the implementation. Until then, please hold off investing further code effort. Appreciated — the encoding work here is careful, and the bounty remains open pending the design outcome.

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.

Scrypt - if statement

2 participants